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/embedded_worker_instance.h" | 5 #include "content/browser/service_worker/embedded_worker_instance.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/bind_helpers.h" | 9 #include "base/bind_helpers.h" |
10 #include "base/macros.h" | 10 #include "base/macros.h" |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 } | 127 } |
128 | 128 |
129 int agent_route_id() const { return agent_route_id_; } | 129 int agent_route_id() const { return agent_route_id_; } |
130 | 130 |
131 private: | 131 private: |
132 const int process_id_; | 132 const int process_id_; |
133 const int agent_route_id_; | 133 const int agent_route_id_; |
134 DISALLOW_COPY_AND_ASSIGN(DevToolsProxy); | 134 DISALLOW_COPY_AND_ASSIGN(DevToolsProxy); |
135 }; | 135 }; |
136 | 136 |
| 137 // A handle for a worker process managed by ServiceWorkerProcessManager on the |
| 138 // UI thread. |
| 139 class EmbeddedWorkerInstance::WorkerProcessHandle { |
| 140 public: |
| 141 WorkerProcessHandle(const base::WeakPtr<ServiceWorkerContextCore>& context, |
| 142 int embedded_worker_id, |
| 143 int process_id) |
| 144 : context_(context), |
| 145 embedded_worker_id_(embedded_worker_id), |
| 146 process_id_(process_id) { |
| 147 DCHECK_NE(ChildProcessHost::kInvalidUniqueID, process_id_); |
| 148 } |
| 149 |
| 150 ~WorkerProcessHandle() { |
| 151 if (context_) |
| 152 context_->process_manager()->ReleaseWorkerProcess(embedded_worker_id_); |
| 153 } |
| 154 |
| 155 int process_id() const { return process_id_; } |
| 156 |
| 157 private: |
| 158 base::WeakPtr<ServiceWorkerContextCore> context_; |
| 159 |
| 160 const int embedded_worker_id_; |
| 161 const int process_id_; |
| 162 |
| 163 DISALLOW_COPY_AND_ASSIGN(WorkerProcessHandle); |
| 164 }; |
| 165 |
| 166 // A task to allocate a worker process and to send a start worker message. This |
| 167 // is created on EmbeddedWorkerInstance::Start(), owned by the instance and |
| 168 // destroyed on EmbeddedWorkerInstance::OnScriptEvaluated(). |
| 169 // We can abort starting worker by destroying this task anytime during the |
| 170 // sequence. |
| 171 class EmbeddedWorkerInstance::StartTask { |
| 172 public: |
| 173 enum class ProcessAllocationState { NOT_ALLOCATED, ALLOCATING, ALLOCATED }; |
| 174 |
| 175 explicit StartTask(EmbeddedWorkerInstance* instance) |
| 176 : instance_(instance), |
| 177 state_(ProcessAllocationState::NOT_ALLOCATED), |
| 178 weak_factory_(this) {} |
| 179 |
| 180 ~StartTask() { |
| 181 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 182 if (!instance_->context_) |
| 183 return; |
| 184 |
| 185 switch (state_) { |
| 186 case ProcessAllocationState::NOT_ALLOCATED: |
| 187 // Not necessary to release a process. |
| 188 break; |
| 189 case ProcessAllocationState::ALLOCATING: |
| 190 // Abort half-baked process allocation on the UI thread. |
| 191 instance_->context_->process_manager()->ReleaseWorkerProcess( |
| 192 instance_->embedded_worker_id()); |
| 193 break; |
| 194 case ProcessAllocationState::ALLOCATED: |
| 195 // Otherwise, the process will be released by EmbeddedWorkerInstance. |
| 196 break; |
| 197 } |
| 198 |
| 199 // Don't have to abort |start_callback_| here. The caller of |
| 200 // EmbeddedWorkerInstance::Start(), that is, ServiceWorkerVersion does not |
| 201 // expect it when the start worker sequence is canceled by Stop() because |
| 202 // the callback, ServiceWorkerVersion::OnStartSentAndScriptEvaluated(), |
| 203 // could drain valid start requests queued in the version. After the worker |
| 204 // is stopped, the version attempts to restart the worker if there are |
| 205 // requests in the queue. See ServiceWorkerVersion::OnStoppedInternal() for |
| 206 // details. |
| 207 // TODO(nhiroki): Reconsider this bizarre layering. |
| 208 } |
| 209 |
| 210 void Start(scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params, |
| 211 const StatusCallback& callback) { |
| 212 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 213 TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker", |
| 214 "EmbeddedWorkerInstance::ProcessAllocate", |
| 215 params.get(), "Scope", params->scope.spec(), |
| 216 "Script URL", params->script_url.spec()); |
| 217 state_ = ProcessAllocationState::ALLOCATING; |
| 218 start_callback_ = callback; |
| 219 |
| 220 GURL scope(params->scope); |
| 221 GURL script_url(params->script_url); |
| 222 instance_->context_->process_manager()->AllocateWorkerProcess( |
| 223 instance_->embedded_worker_id(), scope, script_url, |
| 224 base::Bind(&StartTask::OnProcessAllocated, weak_factory_.GetWeakPtr(), |
| 225 base::Passed(¶ms))); |
| 226 } |
| 227 |
| 228 static void RunStartCallback(StartTask* task, |
| 229 ServiceWorkerStatusCode status) { |
| 230 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 231 StatusCallback callback = task->start_callback_; |
| 232 task->start_callback_.Reset(); |
| 233 callback.Run(status); |
| 234 // |task| may be destroyed. |
| 235 } |
| 236 |
| 237 private: |
| 238 void OnProcessAllocated( |
| 239 scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params, |
| 240 ServiceWorkerStatusCode status, |
| 241 int process_id, |
| 242 bool is_new_process) { |
| 243 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 244 TRACE_EVENT_ASYNC_END1("ServiceWorker", |
| 245 "EmbeddedWorkerInstance::ProcessAllocate", |
| 246 params.get(), "Status", status); |
| 247 |
| 248 if (status != SERVICE_WORKER_OK) { |
| 249 DCHECK_EQ(ChildProcessHost::kInvalidUniqueID, process_id); |
| 250 StatusCallback callback = start_callback_; |
| 251 start_callback_.Reset(); |
| 252 instance_->OnStartFailed(callback, status); |
| 253 // |this| may be destroyed. |
| 254 return; |
| 255 } |
| 256 |
| 257 // Notify the instance that a process is allocated. |
| 258 state_ = ProcessAllocationState::ALLOCATED; |
| 259 instance_->OnProcessAllocated(make_scoped_ptr(new WorkerProcessHandle( |
| 260 instance_->context_, instance_->embedded_worker_id(), process_id))); |
| 261 |
| 262 // Register the instance to DevToolsManager on UI thread. |
| 263 const int64_t service_worker_version_id = params->service_worker_version_id; |
| 264 GURL script_url(params->script_url); |
| 265 BrowserThread::PostTask( |
| 266 BrowserThread::UI, FROM_HERE, |
| 267 base::Bind(RegisterToWorkerDevToolsManagerOnUI, process_id, |
| 268 instance_->context_.get(), instance_->context_, |
| 269 service_worker_version_id, script_url, |
| 270 base::Bind(&StartTask::OnRegisteredToDevToolsManager, |
| 271 weak_factory_.GetWeakPtr(), base::Passed(¶ms), |
| 272 is_new_process))); |
| 273 } |
| 274 |
| 275 void OnRegisteredToDevToolsManager( |
| 276 scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params, |
| 277 bool is_new_process, |
| 278 int worker_devtools_agent_route_id, |
| 279 bool wait_for_debugger) { |
| 280 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 281 |
| 282 // Notify the instance that it is registered to the devtools manager. |
| 283 instance_->OnRegisteredToDevToolsManager( |
| 284 is_new_process, worker_devtools_agent_route_id, wait_for_debugger); |
| 285 |
| 286 params->worker_devtools_agent_route_id = worker_devtools_agent_route_id; |
| 287 params->wait_for_debugger = wait_for_debugger; |
| 288 SendStartWorker(std::move(params)); |
| 289 } |
| 290 |
| 291 void SendStartWorker( |
| 292 scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params) { |
| 293 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 294 ServiceWorkerStatusCode status = instance_->registry_->SendStartWorker( |
| 295 std::move(params), instance_->process_id()); |
| 296 if (status != SERVICE_WORKER_OK) { |
| 297 StatusCallback callback = start_callback_; |
| 298 start_callback_.Reset(); |
| 299 instance_->OnStartFailed(callback, status); |
| 300 // |this| may be destroyed. |
| 301 return; |
| 302 } |
| 303 instance_->OnStartWorkerMessageSent(); |
| 304 |
| 305 // |start_callback_| will be called via RunStartCallback() when the script |
| 306 // is evaluated. |
| 307 } |
| 308 |
| 309 // |instance_| must outlive |this|. |
| 310 EmbeddedWorkerInstance* instance_; |
| 311 |
| 312 StatusCallback start_callback_; |
| 313 ProcessAllocationState state_; |
| 314 |
| 315 base::WeakPtrFactory<StartTask> weak_factory_; |
| 316 |
| 317 DISALLOW_COPY_AND_ASSIGN(StartTask); |
| 318 }; |
| 319 |
137 EmbeddedWorkerInstance::~EmbeddedWorkerInstance() { | 320 EmbeddedWorkerInstance::~EmbeddedWorkerInstance() { |
138 DCHECK(status_ == STOPPING || status_ == STOPPED) << status_; | 321 DCHECK(status_ == STOPPING || status_ == STOPPED) << status_; |
139 devtools_proxy_.reset(); | 322 devtools_proxy_.reset(); |
140 if (context_ && process_id_ != ChildProcessHost::kInvalidUniqueID) | |
141 context_->process_manager()->ReleaseWorkerProcess(embedded_worker_id_); | |
142 if (registry_->GetWorker(embedded_worker_id_)) | 323 if (registry_->GetWorker(embedded_worker_id_)) |
143 registry_->RemoveWorker(process_id_, embedded_worker_id_); | 324 registry_->RemoveWorker(process_id(), embedded_worker_id_); |
| 325 process_handle_.reset(); |
144 } | 326 } |
145 | 327 |
146 void EmbeddedWorkerInstance::Start(int64_t service_worker_version_id, | 328 void EmbeddedWorkerInstance::Start(int64_t service_worker_version_id, |
147 const GURL& scope, | 329 const GURL& scope, |
148 const GURL& script_url, | 330 const GURL& script_url, |
149 const StatusCallback& callback) { | 331 const StatusCallback& callback) { |
150 if (!context_) { | 332 if (!context_) { |
151 callback.Run(SERVICE_WORKER_ERROR_ABORT); | 333 callback.Run(SERVICE_WORKER_ERROR_ABORT); |
152 // |this| may be destroyed by the callback. | 334 // |this| may be destroyed by the callback. |
153 return; | 335 return; |
154 } | 336 } |
155 DCHECK(status_ == STOPPED); | 337 DCHECK(status_ == STOPPED); |
| 338 |
156 // TODO(horo): If we will see crashes here, we have to find the root cause of | 339 // TODO(horo): If we will see crashes here, we have to find the root cause of |
157 // the invalid version ID. Otherwise change CHECK to DCHECK. | 340 // the invalid version ID. Otherwise change CHECK to DCHECK. |
158 CHECK_NE(service_worker_version_id, kInvalidServiceWorkerVersionId); | 341 CHECK_NE(service_worker_version_id, kInvalidServiceWorkerVersionId); |
159 start_timing_ = base::TimeTicks::Now(); | 342 start_timing_ = base::TimeTicks::Now(); |
160 status_ = STARTING; | 343 status_ = STARTING; |
161 starting_phase_ = ALLOCATING_PROCESS; | 344 starting_phase_ = ALLOCATING_PROCESS; |
162 network_accessed_for_script_ = false; | 345 network_accessed_for_script_ = false; |
163 service_registry_.reset(new ServiceRegistryImpl()); | 346 service_registry_.reset(new ServiceRegistryImpl()); |
164 FOR_EACH_OBSERVER(Listener, listener_list_, OnStarting()); | 347 FOR_EACH_OBSERVER(Listener, listener_list_, OnStarting()); |
| 348 |
165 scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params( | 349 scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params( |
166 new EmbeddedWorkerMsg_StartWorker_Params()); | 350 new EmbeddedWorkerMsg_StartWorker_Params()); |
167 TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker", | |
168 "EmbeddedWorkerInstance::ProcessAllocate", | |
169 params.get(), | |
170 "Scope", scope.spec(), | |
171 "Script URL", script_url.spec()); | |
172 params->embedded_worker_id = embedded_worker_id_; | 351 params->embedded_worker_id = embedded_worker_id_; |
173 params->service_worker_version_id = service_worker_version_id; | 352 params->service_worker_version_id = service_worker_version_id; |
174 params->scope = scope; | 353 params->scope = scope; |
175 params->script_url = script_url; | 354 params->script_url = script_url; |
176 params->worker_devtools_agent_route_id = MSG_ROUTING_NONE; | 355 params->worker_devtools_agent_route_id = MSG_ROUTING_NONE; |
177 params->wait_for_debugger = false; | 356 params->wait_for_debugger = false; |
178 params->v8_cache_options = GetV8CacheOptions(); | 357 params->v8_cache_options = GetV8CacheOptions(); |
179 context_->process_manager()->AllocateWorkerProcess( | 358 |
180 embedded_worker_id_, | 359 inflight_start_task_.reset(new StartTask(this)); |
181 scope, | 360 inflight_start_task_->Start(std::move(params), callback); |
182 script_url, | |
183 base::Bind(&EmbeddedWorkerInstance::RunProcessAllocated, | |
184 weak_factory_.GetWeakPtr(), | |
185 context_, | |
186 base::Passed(¶ms), | |
187 callback)); | |
188 } | 361 } |
189 | 362 |
190 ServiceWorkerStatusCode EmbeddedWorkerInstance::Stop() { | 363 ServiceWorkerStatusCode EmbeddedWorkerInstance::Stop() { |
191 DCHECK(status_ == STARTING || status_ == RUNNING) << status_; | 364 DCHECK(status_ == STARTING || status_ == RUNNING) << status_; |
| 365 |
| 366 // Abort an inflight start task. |
| 367 inflight_start_task_.reset(); |
| 368 |
192 ServiceWorkerStatusCode status = | 369 ServiceWorkerStatusCode status = |
193 registry_->StopWorker(process_id_, embedded_worker_id_); | 370 registry_->StopWorker(process_id(), embedded_worker_id_); |
194 UMA_HISTOGRAM_ENUMERATION("ServiceWorker.SendStopWorker.Status", status, | 371 UMA_HISTOGRAM_ENUMERATION("ServiceWorker.SendStopWorker.Status", status, |
195 SERVICE_WORKER_ERROR_MAX_VALUE); | 372 SERVICE_WORKER_ERROR_MAX_VALUE); |
196 // StopWorker could fail if we were starting up and don't have a process yet, | 373 // StopWorker could fail if we were starting up and don't have a process yet, |
197 // or we can no longer communicate with the process. So just detach. | 374 // or we can no longer communicate with the process. So just detach. |
198 if (status != SERVICE_WORKER_OK) { | 375 if (status != SERVICE_WORKER_OK) { |
199 OnDetached(); | 376 OnDetached(); |
200 return status; | 377 return status; |
201 } | 378 } |
202 | 379 |
203 status_ = STOPPING; | 380 status_ = STOPPING; |
204 FOR_EACH_OBSERVER(Listener, listener_list_, OnStopping()); | 381 FOR_EACH_OBSERVER(Listener, listener_list_, OnStopping()); |
205 return status; | 382 return status; |
206 } | 383 } |
207 | 384 |
208 void EmbeddedWorkerInstance::StopIfIdle() { | 385 void EmbeddedWorkerInstance::StopIfIdle() { |
209 if (devtools_attached_) { | 386 if (devtools_attached_) { |
210 if (devtools_proxy_) | 387 if (devtools_proxy_) |
211 devtools_proxy_->NotifyWorkerStopIgnored(); | 388 devtools_proxy_->NotifyWorkerStopIgnored(); |
212 return; | 389 return; |
213 } | 390 } |
214 Stop(); | 391 Stop(); |
215 } | 392 } |
216 | 393 |
217 ServiceWorkerStatusCode EmbeddedWorkerInstance::SendMessage( | 394 ServiceWorkerStatusCode EmbeddedWorkerInstance::SendMessage( |
218 const IPC::Message& message) { | 395 const IPC::Message& message) { |
219 DCHECK_NE(kInvalidEmbeddedWorkerThreadId, thread_id_); | 396 DCHECK_NE(kInvalidEmbeddedWorkerThreadId, thread_id_); |
220 if (status_ != RUNNING && status_ != STARTING) | 397 if (status_ != RUNNING && status_ != STARTING) |
221 return SERVICE_WORKER_ERROR_IPC_FAILED; | 398 return SERVICE_WORKER_ERROR_IPC_FAILED; |
222 return registry_->Send(process_id_, | 399 return registry_->Send(process_id(), |
223 new EmbeddedWorkerContextMsg_MessageToWorker( | 400 new EmbeddedWorkerContextMsg_MessageToWorker( |
224 thread_id_, embedded_worker_id_, message)); | 401 thread_id_, embedded_worker_id_, message)); |
225 } | 402 } |
226 | 403 |
227 ServiceRegistry* EmbeddedWorkerInstance::GetServiceRegistry() { | 404 ServiceRegistry* EmbeddedWorkerInstance::GetServiceRegistry() { |
228 DCHECK(status_ == STARTING || status_ == RUNNING) << status_; | 405 DCHECK(status_ == STARTING || status_ == RUNNING) << status_; |
229 return service_registry_.get(); | 406 return service_registry_.get(); |
230 } | 407 } |
231 | 408 |
232 EmbeddedWorkerInstance::EmbeddedWorkerInstance( | 409 EmbeddedWorkerInstance::EmbeddedWorkerInstance( |
233 base::WeakPtr<ServiceWorkerContextCore> context, | 410 base::WeakPtr<ServiceWorkerContextCore> context, |
234 int embedded_worker_id) | 411 int embedded_worker_id) |
235 : context_(context), | 412 : context_(context), |
236 registry_(context->embedded_worker_registry()), | 413 registry_(context->embedded_worker_registry()), |
237 embedded_worker_id_(embedded_worker_id), | 414 embedded_worker_id_(embedded_worker_id), |
238 status_(STOPPED), | 415 status_(STOPPED), |
239 starting_phase_(NOT_STARTING), | 416 starting_phase_(NOT_STARTING), |
240 process_id_(ChildProcessHost::kInvalidUniqueID), | |
241 thread_id_(kInvalidEmbeddedWorkerThreadId), | 417 thread_id_(kInvalidEmbeddedWorkerThreadId), |
242 devtools_attached_(false), | 418 devtools_attached_(false), |
243 network_accessed_for_script_(false), | 419 network_accessed_for_script_(false), |
244 weak_factory_(this) {} | 420 weak_factory_(this) {} |
245 | 421 |
246 // static | 422 void EmbeddedWorkerInstance::OnProcessAllocated( |
247 void EmbeddedWorkerInstance::RunProcessAllocated( | 423 scoped_ptr<WorkerProcessHandle> handle) { |
248 base::WeakPtr<EmbeddedWorkerInstance> instance, | 424 DCHECK_EQ(STARTING, status_); |
249 base::WeakPtr<ServiceWorkerContextCore> context, | 425 DCHECK(!process_handle_); |
250 scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params, | 426 |
251 const EmbeddedWorkerInstance::StatusCallback& callback, | 427 process_handle_ = std::move(handle); |
252 ServiceWorkerStatusCode status, | 428 starting_phase_ = REGISTERING_TO_DEVTOOLS; |
253 int process_id, | 429 FOR_EACH_OBSERVER(Listener, listener_list_, OnProcessAllocated()); |
254 bool is_new_process) { | |
255 if (!context) { | |
256 callback.Run(SERVICE_WORKER_ERROR_ABORT); | |
257 return; | |
258 } | |
259 if (!instance) { | |
260 if (status == SERVICE_WORKER_OK) { | |
261 // We only have a process allocated if the status is OK. | |
262 context->process_manager()->ReleaseWorkerProcess( | |
263 params->embedded_worker_id); | |
264 } | |
265 callback.Run(SERVICE_WORKER_ERROR_ABORT); | |
266 return; | |
267 } | |
268 instance->ProcessAllocated(std::move(params), callback, process_id, | |
269 is_new_process, status); | |
270 } | 430 } |
271 | 431 |
272 void EmbeddedWorkerInstance::ProcessAllocated( | 432 void EmbeddedWorkerInstance::OnRegisteredToDevToolsManager( |
273 scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params, | |
274 const StatusCallback& callback, | |
275 int process_id, | |
276 bool is_new_process, | |
277 ServiceWorkerStatusCode status) { | |
278 DCHECK_EQ(process_id_, ChildProcessHost::kInvalidUniqueID); | |
279 TRACE_EVENT_ASYNC_END1("ServiceWorker", | |
280 "EmbeddedWorkerInstance::ProcessAllocate", | |
281 params.get(), | |
282 "Status", status); | |
283 if (status != SERVICE_WORKER_OK) { | |
284 OnStartFailed(callback, status); | |
285 return; | |
286 } | |
287 const int64_t service_worker_version_id = params->service_worker_version_id; | |
288 process_id_ = process_id; | |
289 GURL script_url(params->script_url); | |
290 | |
291 // Register this worker to DevToolsManager on UI thread, then continue to | |
292 // call SendStartWorker on IO thread. | |
293 starting_phase_ = REGISTERING_TO_DEVTOOLS; | |
294 BrowserThread::PostTask( | |
295 BrowserThread::UI, FROM_HERE, | |
296 base::Bind(RegisterToWorkerDevToolsManagerOnUI, process_id_, | |
297 context_.get(), context_, service_worker_version_id, | |
298 script_url, | |
299 base::Bind(&EmbeddedWorkerInstance::SendStartWorker, | |
300 weak_factory_.GetWeakPtr(), base::Passed(¶ms), | |
301 callback, is_new_process))); | |
302 } | |
303 | |
304 void EmbeddedWorkerInstance::SendStartWorker( | |
305 scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params, | |
306 const StatusCallback& callback, | |
307 bool is_new_process, | 433 bool is_new_process, |
308 int worker_devtools_agent_route_id, | 434 int worker_devtools_agent_route_id, |
309 bool wait_for_debugger) { | 435 bool wait_for_debugger) { |
310 // We may have been detached or stopped at some point during the start up | |
311 // process, making process_id_ and other state invalid. If that happened, | |
312 // abort instead of trying to send the IPC. | |
313 if (status_ != STARTING) { | |
314 OnStartFailed(callback, SERVICE_WORKER_ERROR_ABORT); | |
315 return; | |
316 } | |
317 | |
318 if (worker_devtools_agent_route_id != MSG_ROUTING_NONE) { | 436 if (worker_devtools_agent_route_id != MSG_ROUTING_NONE) { |
319 DCHECK(!devtools_proxy_); | 437 DCHECK(!devtools_proxy_); |
320 devtools_proxy_.reset(new DevToolsProxy(process_id_, | 438 devtools_proxy_.reset( |
321 worker_devtools_agent_route_id)); | 439 new DevToolsProxy(process_id(), worker_devtools_agent_route_id)); |
322 } | 440 } |
323 params->worker_devtools_agent_route_id = worker_devtools_agent_route_id; | 441 if (wait_for_debugger) { |
324 params->wait_for_debugger = wait_for_debugger; | |
325 if (params->wait_for_debugger) { | |
326 // We don't measure the start time when wait_for_debugger flag is set. So we | 442 // We don't measure the start time when wait_for_debugger flag is set. So we |
327 // set the NULL time here. | 443 // set the NULL time here. |
328 start_timing_ = base::TimeTicks(); | 444 start_timing_ = base::TimeTicks(); |
329 } else { | 445 } else { |
330 DCHECK(!start_timing_.is_null()); | 446 DCHECK(!start_timing_.is_null()); |
331 if (is_new_process) { | 447 if (is_new_process) { |
332 UMA_HISTOGRAM_TIMES("EmbeddedWorkerInstance.NewProcessAllocation", | 448 UMA_HISTOGRAM_TIMES("EmbeddedWorkerInstance.NewProcessAllocation", |
333 base::TimeTicks::Now() - start_timing_); | 449 base::TimeTicks::Now() - start_timing_); |
334 } else { | 450 } else { |
335 UMA_HISTOGRAM_TIMES("EmbeddedWorkerInstance.ExistingProcessAllocation", | 451 UMA_HISTOGRAM_TIMES("EmbeddedWorkerInstance.ExistingProcessAllocation", |
336 base::TimeTicks::Now() - start_timing_); | 452 base::TimeTicks::Now() - start_timing_); |
337 } | 453 } |
338 UMA_HISTOGRAM_BOOLEAN("EmbeddedWorkerInstance.ProcessCreated", | 454 UMA_HISTOGRAM_BOOLEAN("EmbeddedWorkerInstance.ProcessCreated", |
339 is_new_process); | 455 is_new_process); |
340 // Reset |start_timing_| to measure the time excluding the process | 456 // Reset |start_timing_| to measure the time excluding the process |
341 // allocation time. | 457 // allocation time. |
342 start_timing_ = base::TimeTicks::Now(); | 458 start_timing_ = base::TimeTicks::Now(); |
343 } | 459 } |
| 460 } |
344 | 461 |
| 462 void EmbeddedWorkerInstance::OnStartWorkerMessageSent() { |
345 starting_phase_ = SENT_START_WORKER; | 463 starting_phase_ = SENT_START_WORKER; |
346 ServiceWorkerStatusCode status = | 464 FOR_EACH_OBSERVER(Listener, listener_list_, OnStartWorkerMessageSent()); |
347 registry_->SendStartWorker(std::move(params), process_id_); | |
348 if (status != SERVICE_WORKER_OK) { | |
349 OnStartFailed(callback, status); | |
350 return; | |
351 } | |
352 DCHECK(start_callback_.is_null()); | |
353 start_callback_ = callback; | |
354 } | 465 } |
355 | 466 |
356 void EmbeddedWorkerInstance::OnReadyForInspection() { | 467 void EmbeddedWorkerInstance::OnReadyForInspection() { |
357 if (devtools_proxy_) | 468 if (devtools_proxy_) |
358 devtools_proxy_->NotifyWorkerReadyForInspection(); | 469 devtools_proxy_->NotifyWorkerReadyForInspection(); |
359 } | 470 } |
360 | 471 |
361 void EmbeddedWorkerInstance::OnScriptReadStarted() { | 472 void EmbeddedWorkerInstance::OnScriptReadStarted() { |
362 starting_phase_ = SCRIPT_READ_STARTED; | 473 starting_phase_ = SCRIPT_READ_STARTED; |
363 } | 474 } |
(...skipping 25 matching lines...) Expand all Loading... |
389 thread_id_ = thread_id; | 500 thread_id_ = thread_id; |
390 FOR_EACH_OBSERVER(Listener, listener_list_, OnThreadStarted()); | 501 FOR_EACH_OBSERVER(Listener, listener_list_, OnThreadStarted()); |
391 | 502 |
392 mojo::ServiceProviderPtr exposed_services; | 503 mojo::ServiceProviderPtr exposed_services; |
393 service_registry_->Bind(GetProxy(&exposed_services)); | 504 service_registry_->Bind(GetProxy(&exposed_services)); |
394 mojo::ServiceProviderPtr services; | 505 mojo::ServiceProviderPtr services; |
395 mojo::InterfaceRequest<mojo::ServiceProvider> services_request = | 506 mojo::InterfaceRequest<mojo::ServiceProvider> services_request = |
396 GetProxy(&services); | 507 GetProxy(&services); |
397 BrowserThread::PostTask( | 508 BrowserThread::PostTask( |
398 BrowserThread::UI, FROM_HERE, | 509 BrowserThread::UI, FROM_HERE, |
399 base::Bind(SetupMojoOnUIThread, process_id_, thread_id_, | 510 base::Bind(SetupMojoOnUIThread, process_id(), thread_id_, |
400 base::Passed(&services_request), | 511 base::Passed(&services_request), |
401 base::Passed(exposed_services.PassInterface()))); | 512 base::Passed(exposed_services.PassInterface()))); |
402 service_registry_->BindRemoteServiceProvider(std::move(services)); | 513 service_registry_->BindRemoteServiceProvider(std::move(services)); |
403 } | 514 } |
404 | 515 |
405 void EmbeddedWorkerInstance::OnScriptLoadFailed() { | 516 void EmbeddedWorkerInstance::OnScriptLoadFailed() { |
406 FOR_EACH_OBSERVER(Listener, listener_list_, OnScriptLoadFailed()); | 517 FOR_EACH_OBSERVER(Listener, listener_list_, OnScriptLoadFailed()); |
407 } | 518 } |
408 | 519 |
409 void EmbeddedWorkerInstance::OnScriptEvaluated(bool success) { | 520 void EmbeddedWorkerInstance::OnScriptEvaluated(bool success) { |
| 521 if (!inflight_start_task_) |
| 522 return; |
| 523 DCHECK_EQ(STARTING, status_); |
| 524 |
410 starting_phase_ = SCRIPT_EVALUATED; | 525 starting_phase_ = SCRIPT_EVALUATED; |
411 if (start_callback_.is_null()) { | |
412 DVLOG(1) << "Received unexpected OnScriptEvaluated message."; | |
413 return; | |
414 } | |
415 if (success && !start_timing_.is_null()) { | 526 if (success && !start_timing_.is_null()) { |
416 UMA_HISTOGRAM_TIMES("EmbeddedWorkerInstance.ScriptEvaluate", | 527 UMA_HISTOGRAM_TIMES("EmbeddedWorkerInstance.ScriptEvaluate", |
417 base::TimeTicks::Now() - start_timing_); | 528 base::TimeTicks::Now() - start_timing_); |
418 } | 529 } |
419 StatusCallback callback = start_callback_; | 530 |
420 start_callback_.Reset(); | 531 base::WeakPtr<EmbeddedWorkerInstance> weak_this = weak_factory_.GetWeakPtr(); |
421 callback.Run(success ? SERVICE_WORKER_OK | 532 StartTask::RunStartCallback( |
422 : SERVICE_WORKER_ERROR_SCRIPT_EVALUATE_FAILED); | 533 inflight_start_task_.get(), |
| 534 success ? SERVICE_WORKER_OK |
| 535 : SERVICE_WORKER_ERROR_SCRIPT_EVALUATE_FAILED); |
423 // |this| may be destroyed by the callback. | 536 // |this| may be destroyed by the callback. |
424 } | 537 } |
425 | 538 |
426 void EmbeddedWorkerInstance::OnStarted() { | 539 void EmbeddedWorkerInstance::OnStarted() { |
427 // Stop is requested before OnStarted is sent back from the worker. | 540 // Stop is requested before OnStarted is sent back from the worker. |
428 if (status_ == STOPPING) | 541 if (status_ == STOPPING) |
429 return; | 542 return; |
430 DCHECK(status_ == STARTING); | 543 DCHECK(status_ == STARTING); |
431 status_ = RUNNING; | 544 status_ = RUNNING; |
| 545 inflight_start_task_.reset(); |
432 FOR_EACH_OBSERVER(Listener, listener_list_, OnStarted()); | 546 FOR_EACH_OBSERVER(Listener, listener_list_, OnStarted()); |
433 } | 547 } |
434 | 548 |
435 void EmbeddedWorkerInstance::OnStopped() { | 549 void EmbeddedWorkerInstance::OnStopped() { |
436 Status old_status = status_; | 550 Status old_status = status_; |
437 ReleaseProcess(); | 551 ReleaseProcess(); |
438 FOR_EACH_OBSERVER(Listener, listener_list_, OnStopped(old_status)); | 552 FOR_EACH_OBSERVER(Listener, listener_list_, OnStopped(old_status)); |
439 } | 553 } |
440 | 554 |
441 void EmbeddedWorkerInstance::OnDetached() { | 555 void EmbeddedWorkerInstance::OnDetached() { |
442 Status old_status = status_; | 556 Status old_status = status_; |
443 ReleaseProcess(); | 557 ReleaseProcess(); |
444 FOR_EACH_OBSERVER(Listener, listener_list_, OnDetached(old_status)); | 558 FOR_EACH_OBSERVER(Listener, listener_list_, OnDetached(old_status)); |
445 } | 559 } |
446 | 560 |
447 void EmbeddedWorkerInstance::Detach() { | 561 void EmbeddedWorkerInstance::Detach() { |
448 registry_->RemoveWorker(process_id_, embedded_worker_id_); | 562 registry_->RemoveWorker(process_id(), embedded_worker_id_); |
449 OnDetached(); | 563 OnDetached(); |
450 } | 564 } |
451 | 565 |
452 bool EmbeddedWorkerInstance::OnMessageReceived(const IPC::Message& message) { | 566 bool EmbeddedWorkerInstance::OnMessageReceived(const IPC::Message& message) { |
453 ListenerList::Iterator it(&listener_list_); | 567 ListenerList::Iterator it(&listener_list_); |
454 while (Listener* listener = it.GetNext()) { | 568 while (Listener* listener = it.GetNext()) { |
455 if (listener->OnMessageReceived(message)) | 569 if (listener->OnMessageReceived(message)) |
456 return true; | 570 return true; |
457 } | 571 } |
458 return false; | 572 return false; |
(...skipping 16 matching lines...) Expand all Loading... |
475 const base::string16& message, | 589 const base::string16& message, |
476 int line_number, | 590 int line_number, |
477 const GURL& source_url) { | 591 const GURL& source_url) { |
478 FOR_EACH_OBSERVER( | 592 FOR_EACH_OBSERVER( |
479 Listener, | 593 Listener, |
480 listener_list_, | 594 listener_list_, |
481 OnReportConsoleMessage( | 595 OnReportConsoleMessage( |
482 source_identifier, message_level, message, line_number, source_url)); | 596 source_identifier, message_level, message, line_number, source_url)); |
483 } | 597 } |
484 | 598 |
| 599 int EmbeddedWorkerInstance::process_id() const { |
| 600 if (process_handle_) |
| 601 return process_handle_->process_id(); |
| 602 return ChildProcessHost::kInvalidUniqueID; |
| 603 } |
| 604 |
485 int EmbeddedWorkerInstance::worker_devtools_agent_route_id() const { | 605 int EmbeddedWorkerInstance::worker_devtools_agent_route_id() const { |
486 if (devtools_proxy_) | 606 if (devtools_proxy_) |
487 return devtools_proxy_->agent_route_id(); | 607 return devtools_proxy_->agent_route_id(); |
488 return MSG_ROUTING_NONE; | 608 return MSG_ROUTING_NONE; |
489 } | 609 } |
490 | 610 |
491 MessagePortMessageFilter* EmbeddedWorkerInstance::message_port_message_filter() | 611 MessagePortMessageFilter* EmbeddedWorkerInstance::message_port_message_filter() |
492 const { | 612 const { |
493 return registry_->MessagePortMessageFilterForProcess(process_id_); | 613 return registry_->MessagePortMessageFilterForProcess(process_id()); |
494 } | 614 } |
495 | 615 |
496 void EmbeddedWorkerInstance::AddListener(Listener* listener) { | 616 void EmbeddedWorkerInstance::AddListener(Listener* listener) { |
497 listener_list_.AddObserver(listener); | 617 listener_list_.AddObserver(listener); |
498 } | 618 } |
499 | 619 |
500 void EmbeddedWorkerInstance::RemoveListener(Listener* listener) { | 620 void EmbeddedWorkerInstance::RemoveListener(Listener* listener) { |
501 listener_list_.RemoveObserver(listener); | 621 listener_list_.RemoveObserver(listener); |
502 } | 622 } |
503 | 623 |
504 void EmbeddedWorkerInstance::OnNetworkAccessedForScriptLoad() { | 624 void EmbeddedWorkerInstance::OnNetworkAccessedForScriptLoad() { |
505 starting_phase_ = SCRIPT_DOWNLOADING; | 625 starting_phase_ = SCRIPT_DOWNLOADING; |
506 network_accessed_for_script_ = true; | 626 network_accessed_for_script_ = true; |
507 } | 627 } |
508 | 628 |
509 void EmbeddedWorkerInstance::ReleaseProcess() { | 629 void EmbeddedWorkerInstance::ReleaseProcess() { |
| 630 // Abort an inflight start task. |
| 631 inflight_start_task_.reset(); |
| 632 |
510 devtools_proxy_.reset(); | 633 devtools_proxy_.reset(); |
511 if (context_ && process_id_ != ChildProcessHost::kInvalidUniqueID) | 634 process_handle_.reset(); |
512 context_->process_manager()->ReleaseWorkerProcess(embedded_worker_id_); | |
513 status_ = STOPPED; | 635 status_ = STOPPED; |
514 process_id_ = ChildProcessHost::kInvalidUniqueID; | |
515 thread_id_ = kInvalidEmbeddedWorkerThreadId; | 636 thread_id_ = kInvalidEmbeddedWorkerThreadId; |
516 service_registry_.reset(); | 637 service_registry_.reset(); |
517 start_callback_.Reset(); | |
518 } | 638 } |
519 | 639 |
520 void EmbeddedWorkerInstance::OnStartFailed(const StatusCallback& callback, | 640 void EmbeddedWorkerInstance::OnStartFailed(const StatusCallback& callback, |
521 ServiceWorkerStatusCode status) { | 641 ServiceWorkerStatusCode status) { |
522 Status old_status = status_; | 642 Status old_status = status_; |
523 ReleaseProcess(); | 643 ReleaseProcess(); |
524 base::WeakPtr<EmbeddedWorkerInstance> weak_this = weak_factory_.GetWeakPtr(); | 644 base::WeakPtr<EmbeddedWorkerInstance> weak_this = weak_factory_.GetWeakPtr(); |
525 callback.Run(status); | 645 callback.Run(status); |
526 if (weak_this && old_status != STOPPED) | 646 if (weak_this && old_status != STOPPED) |
527 FOR_EACH_OBSERVER(Listener, weak_this->listener_list_, | 647 FOR_EACH_OBSERVER(Listener, weak_this->listener_list_, |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
568 case SCRIPT_READ_FINISHED: | 688 case SCRIPT_READ_FINISHED: |
569 return "Script read finished"; | 689 return "Script read finished"; |
570 case STARTING_PHASE_MAX_VALUE: | 690 case STARTING_PHASE_MAX_VALUE: |
571 NOTREACHED(); | 691 NOTREACHED(); |
572 } | 692 } |
573 NOTREACHED() << phase; | 693 NOTREACHED() << phase; |
574 return std::string(); | 694 return std::string(); |
575 } | 695 } |
576 | 696 |
577 } // namespace content | 697 } // namespace content |
OLD | NEW |