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