Chromium Code Reviews| 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 // | |
| 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(¶ms))); | |
| 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(¶ms), | |
| 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(¶ms), | |
| 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(¶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, | 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |