| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/service_worker/service_worker_registration.h" | 5 #include "content/browser/service_worker/service_worker_registration.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "content/browser/service_worker/service_worker_context_core.h" | 9 #include "content/browser/service_worker/service_worker_context_core.h" |
| 10 #include "content/browser/service_worker/service_worker_context_wrapper.h" |
| 10 #include "content/browser/service_worker/service_worker_info.h" | 11 #include "content/browser/service_worker/service_worker_info.h" |
| 11 #include "content/browser/service_worker/service_worker_metrics.h" | 12 #include "content/browser/service_worker/service_worker_metrics.h" |
| 12 #include "content/browser/service_worker/service_worker_register_job.h" | 13 #include "content/browser/service_worker/service_worker_register_job.h" |
| 13 #include "content/common/service_worker/service_worker_messages.h" | 14 #include "content/common/service_worker/service_worker_messages.h" |
| 14 #include "content/common/service_worker/service_worker_utils.h" | 15 #include "content/common/service_worker/service_worker_utils.h" |
| 15 #include "content/public/browser/browser_thread.h" | 16 #include "content/public/browser/browser_thread.h" |
| 16 | 17 |
| 17 namespace content { | 18 namespace content { |
| 18 | 19 |
| 19 namespace { | 20 namespace { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 30 const GURL& pattern, | 31 const GURL& pattern, |
| 31 int64_t registration_id, | 32 int64_t registration_id, |
| 32 base::WeakPtr<ServiceWorkerContextCore> context) | 33 base::WeakPtr<ServiceWorkerContextCore> context) |
| 33 : pattern_(pattern), | 34 : pattern_(pattern), |
| 34 registration_id_(registration_id), | 35 registration_id_(registration_id), |
| 35 is_deleted_(false), | 36 is_deleted_(false), |
| 36 is_uninstalling_(false), | 37 is_uninstalling_(false), |
| 37 is_uninstalled_(false), | 38 is_uninstalled_(false), |
| 38 should_activate_when_ready_(false), | 39 should_activate_when_ready_(false), |
| 39 resources_total_size_bytes_(0), | 40 resources_total_size_bytes_(0), |
| 40 context_(context) { | 41 context_(context), |
| 42 task_runner_(base::ThreadTaskRunnerHandle::Get()) { |
| 41 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 43 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 42 DCHECK_NE(kInvalidServiceWorkerRegistrationId, registration_id); | 44 DCHECK_NE(kInvalidServiceWorkerRegistrationId, registration_id); |
| 43 DCHECK(context_); | 45 DCHECK(context_); |
| 44 context_->AddLiveRegistration(this); | 46 context_->AddLiveRegistration(this); |
| 45 } | 47 } |
| 46 | 48 |
| 47 ServiceWorkerRegistration::~ServiceWorkerRegistration() { | 49 ServiceWorkerRegistration::~ServiceWorkerRegistration() { |
| 50 // Can be false during shutdown, in which case the DCHECK_CURRENTLY_ON below |
| 51 // would cry. |
| 52 if (!BrowserThread::IsThreadInitialized(BrowserThread::IO)) |
| 53 return; |
| 54 |
| 48 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 55 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 49 DCHECK(!listeners_.might_have_observers()); | 56 DCHECK(!listeners_.might_have_observers()); |
| 50 if (context_) | 57 if (context_) |
| 51 context_->RemoveLiveRegistration(registration_id_); | 58 context_->RemoveLiveRegistration(registration_id_); |
| 52 if (active_version()) | 59 if (active_version()) |
| 53 active_version()->RemoveListener(this); | 60 active_version()->RemoveListener(this); |
| 54 } | 61 } |
| 55 | 62 |
| 56 ServiceWorkerVersion* ServiceWorkerRegistration::GetNewestVersion() const { | 63 ServiceWorkerVersion* ServiceWorkerRegistration::GetNewestVersion() const { |
| 57 if (installing_version()) | 64 if (installing_version()) |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 169 active_version_ = NULL; | 176 active_version_ = NULL; |
| 170 mask->add(ChangedVersionAttributesMask::ACTIVE_VERSION); | 177 mask->add(ChangedVersionAttributesMask::ACTIVE_VERSION); |
| 171 } | 178 } |
| 172 } | 179 } |
| 173 | 180 |
| 174 void ServiceWorkerRegistration::ActivateWaitingVersionWhenReady() { | 181 void ServiceWorkerRegistration::ActivateWaitingVersionWhenReady() { |
| 175 DCHECK(waiting_version()); | 182 DCHECK(waiting_version()); |
| 176 should_activate_when_ready_ = true; | 183 should_activate_when_ready_ = true; |
| 177 | 184 |
| 178 if (!active_version() || !active_version()->HasControllee() || | 185 if (!active_version() || !active_version()->HasControllee() || |
| 179 waiting_version()->skip_waiting()) | 186 waiting_version()->skip_waiting()) { |
| 180 ActivateWaitingVersion(); | 187 ActivateWaitingVersion(false); |
| 188 } |
| 181 } | 189 } |
| 182 | 190 |
| 183 void ServiceWorkerRegistration::ClaimClients() { | 191 void ServiceWorkerRegistration::ClaimClients() { |
| 184 DCHECK(context_); | 192 DCHECK(context_); |
| 185 DCHECK(active_version()); | 193 DCHECK(active_version()); |
| 186 | 194 |
| 187 for (std::unique_ptr<ServiceWorkerContextCore::ProviderHostIterator> it = | 195 for (std::unique_ptr<ServiceWorkerContextCore::ProviderHostIterator> it = |
| 188 context_->GetProviderHostIterator(); | 196 context_->GetProviderHostIterator(); |
| 189 !it->IsAtEnd(); it->Advance()) { | 197 !it->IsAtEnd(); it->Advance()) { |
| 190 ServiceWorkerProviderHost* host = it->GetProviderHost(); | 198 ServiceWorkerProviderHost* host = it->GetProviderHost(); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 236 most_recent_version)); | 244 most_recent_version)); |
| 237 } | 245 } |
| 238 | 246 |
| 239 void ServiceWorkerRegistration::OnNoControllees(ServiceWorkerVersion* version) { | 247 void ServiceWorkerRegistration::OnNoControllees(ServiceWorkerVersion* version) { |
| 240 if (!context_) | 248 if (!context_) |
| 241 return; | 249 return; |
| 242 DCHECK_EQ(active_version(), version); | 250 DCHECK_EQ(active_version(), version); |
| 243 if (is_uninstalling_) | 251 if (is_uninstalling_) |
| 244 Clear(); | 252 Clear(); |
| 245 else if (should_activate_when_ready_) | 253 else if (should_activate_when_ready_) |
| 246 ActivateWaitingVersion(); | 254 ActivateWaitingVersion(true); |
| 247 is_uninstalling_ = false; | 255 is_uninstalling_ = false; |
| 248 should_activate_when_ready_ = false; | 256 should_activate_when_ready_ = false; |
| 249 } | 257 } |
| 250 | 258 |
| 251 void ServiceWorkerRegistration::ActivateWaitingVersion() { | 259 void ServiceWorkerRegistration::ActivateWaitingVersion(bool delay) { |
| 260 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 252 DCHECK(context_); | 261 DCHECK(context_); |
| 253 DCHECK(waiting_version()); | 262 DCHECK(waiting_version()); |
| 254 DCHECK(should_activate_when_ready_); | 263 DCHECK(should_activate_when_ready_); |
| 255 should_activate_when_ready_ = false; | 264 should_activate_when_ready_ = false; |
| 256 scoped_refptr<ServiceWorkerVersion> activating_version = waiting_version(); | 265 scoped_refptr<ServiceWorkerVersion> activating_version = waiting_version(); |
| 257 scoped_refptr<ServiceWorkerVersion> exiting_version = active_version(); | 266 scoped_refptr<ServiceWorkerVersion> exiting_version = active_version(); |
| 258 | 267 |
| 259 if (activating_version->is_redundant()) | 268 if (activating_version->is_redundant()) |
| 260 return; // Activation is no longer relevant. | 269 return; // Activation is no longer relevant. |
| 261 | 270 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 276 SetActiveVersion(activating_version); | 285 SetActiveVersion(activating_version); |
| 277 | 286 |
| 278 // "8. Run the [[UpdateState]] algorithm passing registration.activeWorker and | 287 // "8. Run the [[UpdateState]] algorithm passing registration.activeWorker and |
| 279 // "activating" as arguments." | 288 // "activating" as arguments." |
| 280 activating_version->SetStatus(ServiceWorkerVersion::ACTIVATING); | 289 activating_version->SetStatus(ServiceWorkerVersion::ACTIVATING); |
| 281 // "9. Fire a simple event named controllerchange..." | 290 // "9. Fire a simple event named controllerchange..." |
| 282 if (activating_version->skip_waiting()) | 291 if (activating_version->skip_waiting()) |
| 283 FOR_EACH_OBSERVER(Listener, listeners_, OnSkippedWaiting(this)); | 292 FOR_EACH_OBSERVER(Listener, listeners_, OnSkippedWaiting(this)); |
| 284 | 293 |
| 285 // "10. Queue a task to fire an event named activate..." | 294 // "10. Queue a task to fire an event named activate..." |
| 295 // The browser could be shutting down. To avoid spurious start worker |
| 296 // failures, wait a bit before continuing. |
| 297 if (delay) { |
| 298 task_runner_->PostDelayedTask( |
| 299 FROM_HERE, base::Bind(&ServiceWorkerRegistration::ContinueActivation, |
| 300 this, activating_version), |
| 301 base::TimeDelta::FromSeconds(1)); |
| 302 } else { |
| 303 ContinueActivation(std::move(activating_version)); |
| 304 } |
| 305 } |
| 306 |
| 307 void ServiceWorkerRegistration::ContinueActivation( |
| 308 scoped_refptr<ServiceWorkerVersion> activating_version) { |
| 309 if (!context_) |
| 310 return; |
| 311 if (active_version() != activating_version.get()) |
| 312 return; |
| 313 DCHECK_EQ(ServiceWorkerVersion::ACTIVATING, activating_version->status()); |
| 286 activating_version->RunAfterStartWorker( | 314 activating_version->RunAfterStartWorker( |
| 287 ServiceWorkerMetrics::EventType::ACTIVATE, | 315 ServiceWorkerMetrics::EventType::ACTIVATE, |
| 288 base::Bind(&ServiceWorkerRegistration::DispatchActivateEvent, this, | 316 base::Bind(&ServiceWorkerRegistration::DispatchActivateEvent, this, |
| 289 activating_version), | 317 activating_version), |
| 290 base::Bind(&ServiceWorkerRegistration::OnActivateEventFinished, this, | 318 base::Bind(&ServiceWorkerRegistration::OnActivateEventFinished, this, |
| 291 activating_version)); | 319 activating_version)); |
| 292 } | 320 } |
| 293 | 321 |
| 294 void ServiceWorkerRegistration::DeleteVersion( | 322 void ServiceWorkerRegistration::DeleteVersion( |
| 295 const scoped_refptr<ServiceWorkerVersion>& version) { | 323 const scoped_refptr<ServiceWorkerVersion>& version) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 324 } | 352 } |
| 325 } | 353 } |
| 326 | 354 |
| 327 void ServiceWorkerRegistration::NotifyRegistrationFinished() { | 355 void ServiceWorkerRegistration::NotifyRegistrationFinished() { |
| 328 std::vector<base::Closure> callbacks; | 356 std::vector<base::Closure> callbacks; |
| 329 callbacks.swap(registration_finished_callbacks_); | 357 callbacks.swap(registration_finished_callbacks_); |
| 330 for (const auto& callback : callbacks) | 358 for (const auto& callback : callbacks) |
| 331 callback.Run(); | 359 callback.Run(); |
| 332 } | 360 } |
| 333 | 361 |
| 362 void ServiceWorkerRegistration::SetTaskRunnerForTest( |
| 363 scoped_refptr<base::SingleThreadTaskRunner> task_runner) { |
| 364 task_runner_ = task_runner; |
| 365 } |
| 366 |
| 334 void ServiceWorkerRegistration::RegisterRegistrationFinishedCallback( | 367 void ServiceWorkerRegistration::RegisterRegistrationFinishedCallback( |
| 335 const base::Closure& callback) { | 368 const base::Closure& callback) { |
| 336 // This should only be called if the registration is in progress. | 369 // This should only be called if the registration is in progress. |
| 337 DCHECK(!active_version() && !waiting_version() && !is_uninstalled() && | 370 DCHECK(!active_version() && !waiting_version() && !is_uninstalled() && |
| 338 !is_uninstalling()); | 371 !is_uninstalling()); |
| 339 registration_finished_callbacks_.push_back(callback); | 372 registration_finished_callbacks_.push_back(callback); |
| 340 } | 373 } |
| 341 | 374 |
| 342 void ServiceWorkerRegistration::DispatchActivateEvent( | 375 void ServiceWorkerRegistration::DispatchActivateEvent( |
| 343 const scoped_refptr<ServiceWorkerVersion>& activating_version) { | 376 scoped_refptr<ServiceWorkerVersion> activating_version) { |
| 344 if (activating_version != active_version()) { | 377 if (activating_version != active_version()) { |
| 345 OnActivateEventFinished(activating_version, SERVICE_WORKER_ERROR_FAILED); | 378 OnActivateEventFinished(activating_version, SERVICE_WORKER_ERROR_FAILED); |
| 346 return; | 379 return; |
| 347 } | 380 } |
| 348 | 381 |
| 349 DCHECK_EQ(ServiceWorkerVersion::ACTIVATING, activating_version->status()); | 382 DCHECK_EQ(ServiceWorkerVersion::ACTIVATING, activating_version->status()); |
| 350 DCHECK_EQ(ServiceWorkerVersion::RUNNING, activating_version->running_status()) | 383 DCHECK_EQ(ServiceWorkerVersion::RUNNING, activating_version->running_status()) |
| 351 << "Worker stopped too soon after it was started."; | 384 << "Worker stopped too soon after it was started."; |
| 352 int request_id = activating_version->StartRequest( | 385 int request_id = activating_version->StartRequest( |
| 353 ServiceWorkerMetrics::EventType::ACTIVATE, | 386 ServiceWorkerMetrics::EventType::ACTIVATE, |
| 354 base::Bind(&ServiceWorkerRegistration::OnActivateEventFinished, this, | 387 base::Bind(&ServiceWorkerRegistration::OnActivateEventFinished, this, |
| 355 activating_version)); | 388 activating_version)); |
| 356 activating_version | 389 activating_version |
| 357 ->DispatchSimpleEvent<ServiceWorkerHostMsg_ActivateEventFinished>( | 390 ->DispatchSimpleEvent<ServiceWorkerHostMsg_ActivateEventFinished>( |
| 358 request_id, ServiceWorkerMsg_ActivateEvent(request_id)); | 391 request_id, ServiceWorkerMsg_ActivateEvent(request_id)); |
| 359 } | 392 } |
| 360 | 393 |
| 361 void ServiceWorkerRegistration::OnActivateEventFinished( | 394 void ServiceWorkerRegistration::OnActivateEventFinished( |
| 362 const scoped_refptr<ServiceWorkerVersion>& activating_version, | 395 scoped_refptr<ServiceWorkerVersion> activating_version, |
| 363 ServiceWorkerStatusCode status) { | 396 ServiceWorkerStatusCode status) { |
| 397 // Activate is prone to failing due to shutdown, because it's triggered when |
| 398 // tabs close. |
| 399 bool is_shutdown = |
| 400 !context_ || context_->wrapper()->process_manager()->IsShutdown(); |
| 401 ServiceWorkerMetrics::RecordActivateEventStatus(status, is_shutdown); |
| 402 |
| 364 if (!context_ || activating_version != active_version() || | 403 if (!context_ || activating_version != active_version() || |
| 365 activating_version->status() != ServiceWorkerVersion::ACTIVATING) | 404 activating_version->status() != ServiceWorkerVersion::ACTIVATING) { |
| 366 return; | 405 return; |
| 406 } |
| 367 | 407 |
| 368 // |status| is just for UMA. Once we've attempted to dispatch the activate | 408 // Normally, the worker is committed to become activated once we get here, per |
| 369 // event to an installed worker, it's committed to becoming active. | 409 // spec. E.g., if the script rejected waitUntil or had an unhandled exception, |
| 370 ServiceWorkerMetrics::RecordActivateEventStatus(status); | 410 // it should still be activated. However, if the failure occurred during |
| 411 // shutdown, ignore it to give the worker another chance the next time the |
| 412 // browser starts up. |
| 413 if (is_shutdown && status != SERVICE_WORKER_OK) |
| 414 return; |
| 371 | 415 |
| 372 // "Run the Update State algorithm passing registration's active worker and | 416 // "Run the Update State algorithm passing registration's active worker and |
| 373 // 'activated' as the arguments." | 417 // 'activated' as the arguments." |
| 374 activating_version->SetStatus(ServiceWorkerVersion::ACTIVATED); | 418 activating_version->SetStatus(ServiceWorkerVersion::ACTIVATED); |
| 375 context_->storage()->UpdateToActiveState( | 419 context_->storage()->UpdateToActiveState( |
| 376 this, base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); | 420 this, base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); |
| 377 } | 421 } |
| 378 | 422 |
| 379 void ServiceWorkerRegistration::OnDeleteFinished( | 423 void ServiceWorkerRegistration::OnDeleteFinished( |
| 380 ServiceWorkerStatusCode status) { | 424 ServiceWorkerStatusCode status) { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 428 if (!context_) { | 472 if (!context_) { |
| 429 callback.Run(SERVICE_WORKER_ERROR_ABORT); | 473 callback.Run(SERVICE_WORKER_ERROR_ABORT); |
| 430 return; | 474 return; |
| 431 } | 475 } |
| 432 context_->storage()->NotifyDoneInstallingRegistration( | 476 context_->storage()->NotifyDoneInstallingRegistration( |
| 433 this, version.get(), status); | 477 this, version.get(), status); |
| 434 callback.Run(status); | 478 callback.Run(status); |
| 435 } | 479 } |
| 436 | 480 |
| 437 } // namespace content | 481 } // namespace content |
| OLD | NEW |