| 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 = 30; // 30 secs. |
| 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 embedded_worker_->RemoveListener(this); |
| 107 embedded_worker_->RemoveListener(this); | |
| 108 embedded_worker_.reset(); | |
| 109 } | |
| 110 if (context_) | 114 if (context_) |
| 111 context_->RemoveLiveVersion(version_id_); | 115 context_->RemoveLiveVersion(version_id_); |
| 116 // EmbeddedWorker's dtor sends StopWorker if it's still running. |
| 112 } | 117 } |
| 113 | 118 |
| 114 void ServiceWorkerVersion::SetStatus(Status status) { | 119 void ServiceWorkerVersion::SetStatus(Status status) { |
| 115 if (status_ == status) | 120 if (status_ == status) |
| 116 return; | 121 return; |
| 117 | 122 |
| 118 status_ = status; | 123 status_ = status; |
| 119 | 124 |
| 120 std::vector<base::Closure> callbacks; | 125 std::vector<base::Closure> callbacks; |
| 121 callbacks.swap(status_change_callbacks_); | 126 callbacks.swap(status_change_callbacks_); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 141 embedded_worker()->thread_id()); | 146 embedded_worker()->thread_id()); |
| 142 } | 147 } |
| 143 | 148 |
| 144 void ServiceWorkerVersion::StartWorker(const StatusCallback& callback) { | 149 void ServiceWorkerVersion::StartWorker(const StatusCallback& callback) { |
| 145 StartWorkerWithCandidateProcesses(std::vector<int>(), callback); | 150 StartWorkerWithCandidateProcesses(std::vector<int>(), callback); |
| 146 } | 151 } |
| 147 | 152 |
| 148 void ServiceWorkerVersion::StartWorkerWithCandidateProcesses( | 153 void ServiceWorkerVersion::StartWorkerWithCandidateProcesses( |
| 149 const std::vector<int>& possible_process_ids, | 154 const std::vector<int>& possible_process_ids, |
| 150 const StatusCallback& callback) { | 155 const StatusCallback& callback) { |
| 151 DCHECK(embedded_worker_); | |
| 152 switch (running_status()) { | 156 switch (running_status()) { |
| 153 case RUNNING: | 157 case RUNNING: |
| 154 RunSoon(base::Bind(callback, SERVICE_WORKER_OK)); | 158 RunSoon(base::Bind(callback, SERVICE_WORKER_OK)); |
| 155 return; | 159 return; |
| 156 case STOPPING: | 160 case STOPPING: |
| 157 RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_START_WORKER_FAILED)); | 161 RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_START_WORKER_FAILED)); |
| 158 return; | 162 return; |
| 159 case STOPPED: | 163 case STOPPED: |
| 160 case STARTING: | 164 case STARTING: |
| 161 start_callbacks_.push_back(callback); | 165 start_callbacks_.push_back(callback); |
| 162 if (running_status() == STOPPED) { | 166 if (running_status() == STOPPED) { |
| 163 embedded_worker_->Start( | 167 embedded_worker_->Start( |
| 164 version_id_, | 168 version_id_, |
| 165 scope_, | 169 scope_, |
| 166 script_url_, | 170 script_url_, |
| 167 possible_process_ids, | 171 possible_process_ids, |
| 168 base::Bind(&ServiceWorkerVersion::RunStartWorkerCallbacksOnError, | 172 base::Bind(&ServiceWorkerVersion::RunStartWorkerCallbacksOnError, |
| 169 weak_factory_.GetWeakPtr())); | 173 weak_factory_.GetWeakPtr())); |
| 170 } | 174 } |
| 171 return; | 175 return; |
| 172 } | 176 } |
| 173 } | 177 } |
| 174 | 178 |
| 175 void ServiceWorkerVersion::StopWorker(const StatusCallback& callback) { | 179 void ServiceWorkerVersion::StopWorker(const StatusCallback& callback) { |
| 176 DCHECK(embedded_worker_); | |
| 177 if (running_status() == STOPPED) { | 180 if (running_status() == STOPPED) { |
| 178 RunSoon(base::Bind(callback, SERVICE_WORKER_OK)); | 181 RunSoon(base::Bind(callback, SERVICE_WORKER_OK)); |
| 179 return; | 182 return; |
| 180 } | 183 } |
| 181 if (stop_callbacks_.empty()) { | 184 if (stop_callbacks_.empty()) { |
| 182 ServiceWorkerStatusCode status = embedded_worker_->Stop(); | 185 ServiceWorkerStatusCode status = embedded_worker_->Stop(); |
| 183 if (status != SERVICE_WORKER_OK) { | 186 if (status != SERVICE_WORKER_OK) { |
| 184 RunSoon(base::Bind(callback, status)); | 187 RunSoon(base::Bind(callback, status)); |
| 185 return; | 188 return; |
| 186 } | 189 } |
| 187 } | 190 } |
| 188 stop_callbacks_.push_back(callback); | 191 stop_callbacks_.push_back(callback); |
| 189 } | 192 } |
| 190 | 193 |
| 191 void ServiceWorkerVersion::SendMessage( | 194 void ServiceWorkerVersion::SendMessage( |
| 192 const IPC::Message& message, const StatusCallback& callback) { | 195 const IPC::Message& message, const StatusCallback& callback) { |
| 193 DCHECK(embedded_worker_); | |
| 194 if (running_status() != RUNNING) { | 196 if (running_status() != RUNNING) { |
| 195 // Schedule calling this method after starting the worker. | 197 // Schedule calling this method after starting the worker. |
| 196 StartWorker(base::Bind(&RunTaskAfterStartWorker, | 198 StartWorker(base::Bind(&RunTaskAfterStartWorker, |
| 197 weak_factory_.GetWeakPtr(), callback, | 199 weak_factory_.GetWeakPtr(), callback, |
| 198 base::Bind(&self::SendMessage, | 200 base::Bind(&self::SendMessage, |
| 199 weak_factory_.GetWeakPtr(), | 201 weak_factory_.GetWeakPtr(), |
| 200 message, callback))); | 202 message, callback))); |
| 201 return; | 203 return; |
| 202 } | 204 } |
| 203 | 205 |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 311 bool ServiceWorkerVersion::HasProcessToRun() const { | 313 bool ServiceWorkerVersion::HasProcessToRun() const { |
| 312 return embedded_worker_->HasProcessToRun(); | 314 return embedded_worker_->HasProcessToRun(); |
| 313 } | 315 } |
| 314 | 316 |
| 315 void ServiceWorkerVersion::AddControllee( | 317 void ServiceWorkerVersion::AddControllee( |
| 316 ServiceWorkerProviderHost* provider_host) { | 318 ServiceWorkerProviderHost* provider_host) { |
| 317 DCHECK(!ContainsKey(controllee_map_, provider_host)); | 319 DCHECK(!ContainsKey(controllee_map_, provider_host)); |
| 318 int controllee_id = controllee_by_id_.Add(provider_host); | 320 int controllee_id = controllee_by_id_.Add(provider_host); |
| 319 controllee_map_[provider_host] = controllee_id; | 321 controllee_map_[provider_host] = controllee_id; |
| 320 AddProcessToWorker(provider_host->process_id()); | 322 AddProcessToWorker(provider_host->process_id()); |
| 323 if (stop_worker_timer_.IsRunning()) |
| 324 stop_worker_timer_.Stop(); |
| 321 } | 325 } |
| 322 | 326 |
| 323 void ServiceWorkerVersion::RemoveControllee( | 327 void ServiceWorkerVersion::RemoveControllee( |
| 324 ServiceWorkerProviderHost* provider_host) { | 328 ServiceWorkerProviderHost* provider_host) { |
| 325 ControlleeMap::iterator found = controllee_map_.find(provider_host); | 329 ControlleeMap::iterator found = controllee_map_.find(provider_host); |
| 326 DCHECK(found != controllee_map_.end()); | 330 DCHECK(found != controllee_map_.end()); |
| 327 controllee_by_id_.Remove(found->second); | 331 controllee_by_id_.Remove(found->second); |
| 328 controllee_map_.erase(found); | 332 controllee_map_.erase(found); |
| 329 RemoveProcessFromWorker(provider_host->process_id()); | 333 RemoveProcessFromWorker(provider_host->process_id()); |
| 334 if (!HasControllee()) |
| 335 ScheduleStopWorker(); |
| 330 // TODO(kinuko): Fire NoControllees notification when the # of controllees | 336 // TODO(kinuko): Fire NoControllees notification when the # of controllees |
| 331 // reaches 0, so that a new pending version can be activated (which will | 337 // reaches 0, so that a new pending version can be activated (which will |
| 332 // deactivate this version). | 338 // deactivate this version). |
| 333 // TODO(michaeln): On no controllees call storage DeleteVersionResources | 339 // TODO(michaeln): On no controllees call storage DeleteVersionResources |
| 334 // if this version has been deactivated. Probably storage can listen for | 340 // if this version has been deactivated. Probably storage can listen for |
| 335 // NoControllees for versions that have been deleted. | 341 // NoControllees for versions that have been deleted. |
| 336 } | 342 } |
| 337 | 343 |
| 338 void ServiceWorkerVersion::AddPendingControllee( | 344 void ServiceWorkerVersion::AddPendingControllee( |
| 339 ServiceWorkerProviderHost* provider_host) { | 345 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) { | 564 const std::vector<int>& sent_message_port_ids) { |
| 559 ServiceWorkerProviderHost* provider_host = | 565 ServiceWorkerProviderHost* provider_host = |
| 560 controllee_by_id_.Lookup(client_id); | 566 controllee_by_id_.Lookup(client_id); |
| 561 if (!provider_host) { | 567 if (!provider_host) { |
| 562 // The client may already have been closed, just ignore. | 568 // The client may already have been closed, just ignore. |
| 563 return; | 569 return; |
| 564 } | 570 } |
| 565 provider_host->PostMessage(message, sent_message_port_ids); | 571 provider_host->PostMessage(message, sent_message_port_ids); |
| 566 } | 572 } |
| 567 | 573 |
| 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 |
| 568 } // namespace content | 588 } // namespace content |
| OLD | NEW |