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

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

Powered by Google App Engine
This is Rietveld 408576698