Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(374)

Side by Side Diff: content/browser/service_worker/embedded_worker_instance.cc

Issue 1569773002: ServiceWorker: Make start worker sequence cancelable (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: address review comments Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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(&params)));
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(&params),
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(&params),
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(&params),
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698