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/service_worker/embedded_worker_instance.h" | 10 #include "content/browser/service_worker/embedded_worker_instance.h" |
11 #include "content/browser/service_worker/embedded_worker_registry.h" | 11 #include "content/browser/service_worker/embedded_worker_registry.h" |
12 #include "content/browser/service_worker/service_worker_context_core.h" | 12 #include "content/browser/service_worker/service_worker_context_core.h" |
13 #include "content/browser/service_worker/service_worker_registration.h" | 13 #include "content/browser/service_worker/service_worker_registration.h" |
14 #include "content/browser/service_worker/service_worker_utils.h" | |
14 #include "content/common/service_worker/service_worker_messages.h" | 15 #include "content/common/service_worker/service_worker_messages.h" |
15 #include "content/public/browser/browser_thread.h" | 16 #include "content/public/browser/browser_thread.h" |
16 #include "content/public/common/content_switches.h" | 17 #include "content/public/common/content_switches.h" |
17 | 18 |
18 namespace content { | 19 namespace content { |
19 | 20 |
20 typedef ServiceWorkerVersion::StatusCallback StatusCallback; | 21 typedef ServiceWorkerVersion::StatusCallback StatusCallback; |
21 typedef ServiceWorkerVersion::MessageCallback MessageCallback; | 22 typedef ServiceWorkerVersion::MessageCallback MessageCallback; |
22 | 23 |
23 namespace { | 24 namespace { |
24 | 25 |
26 // Default delay to stop the worker context after all documents that | |
27 // are associated to the worker are closed. | |
28 // (Note that if all references to the version is dropped the worker | |
29 // is also stopped without delay) | |
30 const int64 kStopWorkerDelay = 5 * 60; // 5 mins. | |
31 | |
25 void RunSoon(const base::Closure& callback) { | 32 void RunSoon(const base::Closure& callback) { |
26 if (!callback.is_null()) | 33 if (!callback.is_null()) |
27 base::MessageLoop::current()->PostTask(FROM_HERE, callback); | 34 base::MessageLoop::current()->PostTask(FROM_HERE, callback); |
28 } | 35 } |
29 | 36 |
30 template <typename CallbackArray, typename Arg> | 37 template <typename CallbackArray, typename Arg> |
31 void RunCallbacks(ServiceWorkerVersion* version, | 38 void RunCallbacks(ServiceWorkerVersion* version, |
32 CallbackArray* callbacks_ptr, | 39 CallbackArray* callbacks_ptr, |
33 const Arg& arg) { | 40 const Arg& arg) { |
34 CallbackArray callbacks; | 41 CallbackArray callbacks; |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
96 registration_id_ = registration->id(); | 103 registration_id_ = registration->id(); |
97 script_url_ = registration->script_url(); | 104 script_url_ = registration->script_url(); |
98 scope_ = registration->pattern(); | 105 scope_ = registration->pattern(); |
99 } | 106 } |
100 context_->AddLiveVersion(this); | 107 context_->AddLiveVersion(this); |
101 embedded_worker_ = context_->embedded_worker_registry()->CreateWorker(); | 108 embedded_worker_ = context_->embedded_worker_registry()->CreateWorker(); |
102 embedded_worker_->AddListener(this); | 109 embedded_worker_->AddListener(this); |
103 } | 110 } |
104 | 111 |
105 ServiceWorkerVersion::~ServiceWorkerVersion() { | 112 ServiceWorkerVersion::~ServiceWorkerVersion() { |
106 if (embedded_worker_) { | 113 if (running_status() == RUNNING) { |
107 embedded_worker_->RemoveListener(this); | 114 if (stop_worker_timer_.IsRunning()) |
108 embedded_worker_.reset(); | 115 stop_worker_timer_.Stop(); |
116 embedded_worker_->Stop(); | |
michaeln
2014/05/14 19:44:23
What happens when a running worker instance is del
kinuko
2014/05/14 21:56:30
Yes, and this CL does so (stops the worker if it's
kinuko
2014/05/14 22:00:26
(I could change this to call StopWorker() if it's
michaeln
2014/05/14 23:20:21
i was referring to EmbeddedWorkerInstance class, s
kinuko
2014/05/14 23:50:06
Hmm... ok will move the Stop part to EmbeddedWorke
kinuko
2014/05/15 17:17:26
Done.
| |
109 } | 117 } |
118 embedded_worker_->RemoveListener(this); | |
119 embedded_worker_.reset(); | |
110 if (context_) | 120 if (context_) |
111 context_->RemoveLiveVersion(version_id_); | 121 context_->RemoveLiveVersion(version_id_); |
112 } | 122 } |
113 | 123 |
114 void ServiceWorkerVersion::SetStatus(Status status) { | 124 void ServiceWorkerVersion::SetStatus(Status status) { |
115 if (status_ == status) | 125 if (status_ == status) |
116 return; | 126 return; |
117 | 127 |
118 status_ = status; | 128 status_ = status; |
119 | 129 |
(...skipping 21 matching lines...) Expand all Loading... | |
141 embedded_worker()->thread_id()); | 151 embedded_worker()->thread_id()); |
142 } | 152 } |
143 | 153 |
144 void ServiceWorkerVersion::StartWorker(const StatusCallback& callback) { | 154 void ServiceWorkerVersion::StartWorker(const StatusCallback& callback) { |
145 StartWorkerWithCandidateProcesses(std::vector<int>(), callback); | 155 StartWorkerWithCandidateProcesses(std::vector<int>(), callback); |
146 } | 156 } |
147 | 157 |
148 void ServiceWorkerVersion::StartWorkerWithCandidateProcesses( | 158 void ServiceWorkerVersion::StartWorkerWithCandidateProcesses( |
149 const std::vector<int>& possible_process_ids, | 159 const std::vector<int>& possible_process_ids, |
150 const StatusCallback& callback) { | 160 const StatusCallback& callback) { |
151 DCHECK(embedded_worker_); | |
152 switch (running_status()) { | 161 switch (running_status()) { |
153 case RUNNING: | 162 case RUNNING: |
154 RunSoon(base::Bind(callback, SERVICE_WORKER_OK)); | 163 RunSoon(base::Bind(callback, SERVICE_WORKER_OK)); |
155 return; | 164 return; |
156 case STOPPING: | 165 case STOPPING: |
157 RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_START_WORKER_FAILED)); | 166 RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_START_WORKER_FAILED)); |
158 return; | 167 return; |
159 case STOPPED: | 168 case STOPPED: |
160 case STARTING: | 169 case STARTING: |
161 start_callbacks_.push_back(callback); | 170 start_callbacks_.push_back(callback); |
162 if (running_status() == STOPPED) { | 171 if (running_status() == STOPPED) { |
163 embedded_worker_->Start( | 172 embedded_worker_->Start( |
164 version_id_, | 173 version_id_, |
165 scope_, | 174 scope_, |
166 script_url_, | 175 script_url_, |
167 possible_process_ids, | 176 possible_process_ids, |
168 base::Bind(&ServiceWorkerVersion::RunStartWorkerCallbacksOnError, | 177 base::Bind(&ServiceWorkerVersion::RunStartWorkerCallbacksOnError, |
169 weak_factory_.GetWeakPtr())); | 178 weak_factory_.GetWeakPtr())); |
170 } | 179 } |
171 return; | 180 return; |
172 } | 181 } |
173 } | 182 } |
174 | 183 |
175 void ServiceWorkerVersion::StopWorker(const StatusCallback& callback) { | 184 void ServiceWorkerVersion::StopWorker(const StatusCallback& callback) { |
176 DCHECK(embedded_worker_); | |
177 if (running_status() == STOPPED) { | 185 if (running_status() == STOPPED) { |
178 RunSoon(base::Bind(callback, SERVICE_WORKER_OK)); | 186 RunSoon(base::Bind(callback, SERVICE_WORKER_OK)); |
179 return; | 187 return; |
180 } | 188 } |
181 if (stop_callbacks_.empty()) { | 189 if (stop_callbacks_.empty()) { |
182 ServiceWorkerStatusCode status = embedded_worker_->Stop(); | 190 ServiceWorkerStatusCode status = embedded_worker_->Stop(); |
183 if (status != SERVICE_WORKER_OK) { | 191 if (status != SERVICE_WORKER_OK) { |
184 RunSoon(base::Bind(callback, status)); | 192 RunSoon(base::Bind(callback, status)); |
185 return; | 193 return; |
186 } | 194 } |
187 } | 195 } |
188 stop_callbacks_.push_back(callback); | 196 stop_callbacks_.push_back(callback); |
189 } | 197 } |
190 | 198 |
191 void ServiceWorkerVersion::SendMessage( | 199 void ServiceWorkerVersion::SendMessage( |
192 const IPC::Message& message, const StatusCallback& callback) { | 200 const IPC::Message& message, const StatusCallback& callback) { |
193 DCHECK(embedded_worker_); | |
michaeln
2014/05/14 19:44:23
why remove these?
kinuko
2014/05/14 21:56:30
Since we no longer reset embedded_worker_ anywhere
michaeln
2014/05/14 23:20:21
k... got it
| |
194 if (running_status() != RUNNING) { | 201 if (running_status() != RUNNING) { |
195 // Schedule calling this method after starting the worker. | 202 // Schedule calling this method after starting the worker. |
196 StartWorker(base::Bind(&RunTaskAfterStartWorker, | 203 StartWorker(base::Bind(&RunTaskAfterStartWorker, |
197 weak_factory_.GetWeakPtr(), callback, | 204 weak_factory_.GetWeakPtr(), callback, |
198 base::Bind(&self::SendMessage, | 205 base::Bind(&self::SendMessage, |
199 weak_factory_.GetWeakPtr(), | 206 weak_factory_.GetWeakPtr(), |
200 message, callback))); | 207 message, callback))); |
201 return; | 208 return; |
202 } | 209 } |
203 | 210 |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
311 bool ServiceWorkerVersion::HasProcessToRun() const { | 318 bool ServiceWorkerVersion::HasProcessToRun() const { |
312 return embedded_worker_->HasProcessToRun(); | 319 return embedded_worker_->HasProcessToRun(); |
313 } | 320 } |
314 | 321 |
315 void ServiceWorkerVersion::AddControllee( | 322 void ServiceWorkerVersion::AddControllee( |
316 ServiceWorkerProviderHost* provider_host) { | 323 ServiceWorkerProviderHost* provider_host) { |
317 DCHECK(!ContainsKey(controllee_map_, provider_host)); | 324 DCHECK(!ContainsKey(controllee_map_, provider_host)); |
318 int controllee_id = controllee_by_id_.Add(provider_host); | 325 int controllee_id = controllee_by_id_.Add(provider_host); |
319 controllee_map_[provider_host] = controllee_id; | 326 controllee_map_[provider_host] = controllee_id; |
320 AddProcessToWorker(provider_host->process_id()); | 327 AddProcessToWorker(provider_host->process_id()); |
328 if (stop_worker_timer_.IsRunning()) | |
329 stop_worker_timer_.Stop(); | |
321 } | 330 } |
322 | 331 |
323 void ServiceWorkerVersion::RemoveControllee( | 332 void ServiceWorkerVersion::RemoveControllee( |
324 ServiceWorkerProviderHost* provider_host) { | 333 ServiceWorkerProviderHost* provider_host) { |
325 ControlleeMap::iterator found = controllee_map_.find(provider_host); | 334 ControlleeMap::iterator found = controllee_map_.find(provider_host); |
326 DCHECK(found != controllee_map_.end()); | 335 DCHECK(found != controllee_map_.end()); |
327 controllee_by_id_.Remove(found->second); | 336 controllee_by_id_.Remove(found->second); |
328 controllee_map_.erase(found); | 337 controllee_map_.erase(found); |
329 RemoveProcessFromWorker(provider_host->process_id()); | 338 RemoveProcessFromWorker(provider_host->process_id()); |
339 if (!HasControllee()) | |
340 ScheduleStopWorker(); | |
330 // TODO(kinuko): Fire NoControllees notification when the # of controllees | 341 // TODO(kinuko): Fire NoControllees notification when the # of controllees |
331 // reaches 0, so that a new pending version can be activated (which will | 342 // reaches 0, so that a new pending version can be activated (which will |
332 // deactivate this version). | 343 // deactivate this version). |
333 // TODO(michaeln): On no controllees call storage DeleteVersionResources | 344 // TODO(michaeln): On no controllees call storage DeleteVersionResources |
334 // if this version has been deactivated. Probably storage can listen for | 345 // if this version has been deactivated. Probably storage can listen for |
335 // NoControllees for versions that have been deleted. | 346 // NoControllees for versions that have been deleted. |
336 } | 347 } |
337 | 348 |
338 void ServiceWorkerVersion::AddPendingControllee( | 349 void ServiceWorkerVersion::AddPendingControllee( |
339 ServiceWorkerProviderHost* provider_host) { | 350 ServiceWorkerProviderHost* provider_host) { |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
558 const std::vector<int>& sent_message_port_ids) { | 569 const std::vector<int>& sent_message_port_ids) { |
559 ServiceWorkerProviderHost* provider_host = | 570 ServiceWorkerProviderHost* provider_host = |
560 controllee_by_id_.Lookup(client_id); | 571 controllee_by_id_.Lookup(client_id); |
561 if (!provider_host) { | 572 if (!provider_host) { |
562 // The client may already have been closed, just ignore. | 573 // The client may already have been closed, just ignore. |
563 return; | 574 return; |
564 } | 575 } |
565 provider_host->PostMessage(message, sent_message_port_ids); | 576 provider_host->PostMessage(message, sent_message_port_ids); |
566 } | 577 } |
567 | 578 |
579 void ServiceWorkerVersion::ScheduleStopWorker() { | |
580 if (running_status() != RUNNING) | |
581 return; | |
582 if (stop_worker_timer_.IsRunning()) { | |
583 stop_worker_timer_.Reset(); | |
584 } else { | |
585 stop_worker_timer_.Start( | |
586 FROM_HERE, base::TimeDelta::FromSeconds(kStopWorkerDelay), | |
587 base::Bind(&ServiceWorkerVersion::StopWorker, | |
588 weak_factory_.GetWeakPtr(), | |
589 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback))); | |
590 } | |
591 } | |
592 | |
568 } // namespace content | 593 } // namespace content |
OLD | NEW |