Chromium Code Reviews| 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_version.h" | 5 #include "content/browser/service_worker/service_worker_version.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/stl_util.h" | 8 #include "base/stl_util.h" |
| 9 #include "base/strings/string16.h" | 9 #include "base/strings/string16.h" |
| 10 #include "content/browser/message_port_message_filter.h" | 10 #include "content/browser/message_port_message_filter.h" |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 106 const GURL& script_url, | 106 const GURL& script_url, |
| 107 int64 version_id, | 107 int64 version_id, |
| 108 base::WeakPtr<ServiceWorkerContextCore> context) | 108 base::WeakPtr<ServiceWorkerContextCore> context) |
| 109 : version_id_(version_id), | 109 : version_id_(version_id), |
| 110 registration_id_(kInvalidServiceWorkerVersionId), | 110 registration_id_(kInvalidServiceWorkerVersionId), |
| 111 script_url_(script_url), | 111 script_url_(script_url), |
| 112 status_(NEW), | 112 status_(NEW), |
| 113 context_(context), | 113 context_(context), |
| 114 script_cache_map_(this, context), | 114 script_cache_map_(this, context), |
| 115 is_doomed_(false), | 115 is_doomed_(false), |
| 116 keep_alive_mode_(context->keep_alive_mode()), | |
| 116 weak_factory_(this) { | 117 weak_factory_(this) { |
| 117 DCHECK(context_); | 118 DCHECK(context_); |
| 118 DCHECK(registration); | 119 DCHECK(registration); |
| 119 if (registration) { | 120 if (registration) { |
| 120 registration_id_ = registration->id(); | 121 registration_id_ = registration->id(); |
| 121 scope_ = registration->pattern(); | 122 scope_ = registration->pattern(); |
| 122 } | 123 } |
| 123 context_->AddLiveVersion(this); | 124 context_->AddLiveVersion(this); |
| 124 embedded_worker_ = context_->embedded_worker_registry()->CreateWorker(); | 125 embedded_worker_ = context_->embedded_worker_registry()->CreateWorker(); |
| 125 embedded_worker_->AddListener(this); | 126 embedded_worker_->AddListener(this); |
| 126 } | 127 } |
| 127 | 128 |
| 128 ServiceWorkerVersion::~ServiceWorkerVersion() { | 129 ServiceWorkerVersion::~ServiceWorkerVersion() { |
| 129 embedded_worker_->RemoveListener(this); | 130 embedded_worker_->RemoveListener(this); |
| 130 if (context_) | 131 if (context_) |
| 131 context_->RemoveLiveVersion(version_id_); | 132 context_->RemoveLiveVersion(version_id_); |
| 132 // EmbeddedWorker's dtor sends StopWorker if it's still running. | 133 // EmbeddedWorker's dtor sends StopWorker if it's still running. |
| 133 } | 134 } |
| 134 | 135 |
| 135 void ServiceWorkerVersion::SetStatus(Status status) { | 136 void ServiceWorkerVersion::SetStatus(Status status) { |
| 136 if (status_ == status) | 137 if (status_ == status) |
| 137 return; | 138 return; |
| 138 | 139 |
| 139 // Schedule to stop worker after registration successfully completed. | |
| 140 if (status_ == ACTIVATING && status == ACTIVATED && !HasControllee()) | |
| 141 ScheduleStopWorker(); | |
| 142 | |
| 143 status_ = status; | 140 status_ = status; |
| 144 | 141 |
| 145 std::vector<base::Closure> callbacks; | 142 std::vector<base::Closure> callbacks; |
| 146 callbacks.swap(status_change_callbacks_); | 143 callbacks.swap(status_change_callbacks_); |
| 147 for (const auto& callback : callbacks) | 144 for (const auto& callback : callbacks) |
| 148 callback.Run(); | 145 callback.Run(); |
| 149 | 146 |
| 150 FOR_EACH_OBSERVER(Listener, listeners_, OnVersionStateChanged(this)); | 147 FOR_EACH_OBSERVER(Listener, listeners_, OnVersionStateChanged(this)); |
| 151 } | 148 } |
| 152 | 149 |
| (...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 525 } | 522 } |
| 526 | 523 |
| 527 void ServiceWorkerVersion::Doom() { | 524 void ServiceWorkerVersion::Doom() { |
| 528 if (is_doomed_) | 525 if (is_doomed_) |
| 529 return; | 526 return; |
| 530 is_doomed_ = true; | 527 is_doomed_ = true; |
| 531 if (!HasControllee()) | 528 if (!HasControllee()) |
| 532 DoomInternal(); | 529 DoomInternal(); |
| 533 } | 530 } |
| 534 | 531 |
| 532 void ServiceWorkerVersion::SetKeepAliveMode(bool keep_alive) { | |
| 533 keep_alive_mode_ = keep_alive; | |
| 534 | |
| 535 if (keep_alive_mode_) | |
| 536 CancelStopWorker(); | |
| 537 else | |
| 538 ScheduleStopWorker(); | |
| 539 } | |
| 540 | |
| 535 void ServiceWorkerVersion::OnStarted() { | 541 void ServiceWorkerVersion::OnStarted() { |
| 536 DCHECK_EQ(RUNNING, running_status()); | 542 DCHECK_EQ(RUNNING, running_status()); |
| 537 DCHECK(cache_listener_.get()); | 543 DCHECK(cache_listener_.get()); |
| 538 if (status() == ACTIVATED && !HasControllee()) | 544 ScheduleStopWorker(); |
| 539 ScheduleStopWorker(); | |
| 540 // Fire all start callbacks. | 545 // Fire all start callbacks. |
| 541 RunCallbacks(this, &start_callbacks_, SERVICE_WORKER_OK); | 546 RunCallbacks(this, &start_callbacks_, SERVICE_WORKER_OK); |
| 542 FOR_EACH_OBSERVER(Listener, listeners_, OnWorkerStarted(this)); | 547 FOR_EACH_OBSERVER(Listener, listeners_, OnWorkerStarted(this)); |
| 543 } | 548 } |
| 544 | 549 |
| 545 void ServiceWorkerVersion::OnStopped( | 550 void ServiceWorkerVersion::OnStopped( |
| 546 EmbeddedWorkerInstance::Status old_status) { | 551 EmbeddedWorkerInstance::Status old_status) { |
| 547 DCHECK_EQ(STOPPED, running_status()); | 552 DCHECK_EQ(STOPPED, running_status()); |
| 548 scoped_refptr<ServiceWorkerVersion> protect(this); | 553 scoped_refptr<ServiceWorkerVersion> protect(this); |
| 549 | 554 |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 839 ServiceWorkerProviderHost* provider_host = | 844 ServiceWorkerProviderHost* provider_host = |
| 840 controllee_by_id_.Lookup(client_id); | 845 controllee_by_id_.Lookup(client_id); |
| 841 if (!provider_host) { | 846 if (!provider_host) { |
| 842 // The client may already have been closed, just ignore. | 847 // The client may already have been closed, just ignore. |
| 843 return; | 848 return; |
| 844 } | 849 } |
| 845 provider_host->PostMessage(message, sent_message_port_ids); | 850 provider_host->PostMessage(message, sent_message_port_ids); |
| 846 } | 851 } |
| 847 | 852 |
| 848 void ServiceWorkerVersion::ScheduleStopWorker() { | 853 void ServiceWorkerVersion::ScheduleStopWorker() { |
| 849 if (running_status() != RUNNING) | 854 if (running_status() != RUNNING || |
| 855 HasControllee() || | |
|
falken
2014/12/08 02:30:16
My first reaction was we should still stop the wor
| |
| 856 keep_alive_mode_) { | |
| 850 return; | 857 return; |
| 858 } | |
| 851 if (stop_worker_timer_.IsRunning()) { | 859 if (stop_worker_timer_.IsRunning()) { |
| 852 stop_worker_timer_.Reset(); | 860 stop_worker_timer_.Reset(); |
| 853 return; | 861 return; |
| 854 } | 862 } |
| 855 stop_worker_timer_.Start( | 863 stop_worker_timer_.Start( |
| 856 FROM_HERE, base::TimeDelta::FromSeconds(kStopWorkerDelay), | 864 FROM_HERE, base::TimeDelta::FromSeconds(kStopWorkerDelay), |
| 857 base::Bind(&ServiceWorkerVersion::StopWorker, | 865 base::Bind(&ServiceWorkerVersion::MaybeStopWorker, |
| 858 weak_factory_.GetWeakPtr(), | 866 weak_factory_.GetWeakPtr())); |
| 859 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback))); | 867 } |
| 868 | |
| 869 void ServiceWorkerVersion::CancelStopWorker() { | |
| 870 if (stop_worker_timer_.IsRunning()) | |
| 871 stop_worker_timer_.Stop(); | |
| 872 } | |
| 873 | |
| 874 void ServiceWorkerVersion::MaybeStopWorker() { | |
| 875 // Reschedule the stop the worker while there're inflight requests. | |
| 876 // (Note: we'll probably need to revisit this so that we can kill 'bad' SW. | |
| 877 // See https://github.com/slightlyoff/ServiceWorker/issues/527) | |
| 878 if (HasInflightRequests()) { | |
| 879 ScheduleStopWorker(); | |
| 880 return; | |
| 881 } | |
| 882 StopWorker(base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); | |
| 883 } | |
| 884 | |
| 885 bool ServiceWorkerVersion::HasInflightRequests() const { | |
| 886 return | |
| 887 !activate_callbacks_.IsEmpty() || | |
| 888 !install_callbacks_.IsEmpty() || | |
| 889 !fetch_callbacks_.IsEmpty() || | |
| 890 !sync_callbacks_.IsEmpty() || | |
| 891 !notification_click_callbacks_.IsEmpty() || | |
| 892 !push_callbacks_.IsEmpty() || | |
| 893 !geofencing_callbacks_.IsEmpty(); | |
| 860 } | 894 } |
| 861 | 895 |
| 862 void ServiceWorkerVersion::DoomInternal() { | 896 void ServiceWorkerVersion::DoomInternal() { |
| 863 DCHECK(!HasControllee()); | 897 DCHECK(!HasControllee()); |
| 864 SetStatus(REDUNDANT); | 898 SetStatus(REDUNDANT); |
| 865 StopWorker(base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); | 899 StopWorker(base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); |
| 866 if (!context_) | 900 if (!context_) |
| 867 return; | 901 return; |
| 868 std::vector<ServiceWorkerDatabase::ResourceRecord> resources; | 902 std::vector<ServiceWorkerDatabase::ResourceRecord> resources; |
| 869 script_cache_map_.GetResources(&resources); | 903 script_cache_map_.GetResources(&resources); |
| 870 context_->storage()->PurgeResources(resources); | 904 context_->storage()->PurgeResources(resources); |
| 871 } | 905 } |
| 872 | 906 |
| 873 } // namespace content | 907 } // namespace content |
| OLD | NEW |