Chromium Code Reviews| Index: content/browser/service_worker/embedded_worker_instance.cc |
| diff --git a/content/browser/service_worker/embedded_worker_instance.cc b/content/browser/service_worker/embedded_worker_instance.cc |
| index 24d2a9529a9843eb6dbf7c36e44efeabd748dd4d..cdeb4c5007108aaa9ff8c7a921b9dbc76b423476 100644 |
| --- a/content/browser/service_worker/embedded_worker_instance.cc |
| +++ b/content/browser/service_worker/embedded_worker_instance.cc |
| @@ -4,14 +4,20 @@ |
| #include "content/browser/service_worker/embedded_worker_instance.h" |
| +#include "base/bind_helpers.h" |
| +#include "content/browser/devtools/embedded_worker_devtools_manager.h" |
| #include "content/browser/service_worker/embedded_worker_registry.h" |
| +#include "content/browser/service_worker/service_worker_context_core.h" |
| #include "content/common/service_worker/embedded_worker_messages.h" |
| +#include "content/public/browser/browser_thread.h" |
| +#include "content/public/browser/render_process_host.h" |
| #include "ipc/ipc_message.h" |
| #include "url/gurl.h" |
| namespace content { |
| namespace { |
| + |
| // Functor to sort by the .second element of a struct. |
| struct SecondGreater { |
| template <typename Value> |
| @@ -19,30 +25,106 @@ struct SecondGreater { |
| return lhs.second > rhs.second; |
| } |
| }; |
| + |
| +void NotifyWorkerContextStarted(int worker_process_id, int worker_route_id) { |
| + if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| + BrowserThread::PostTask( |
| + BrowserThread::UI, |
| + FROM_HERE, |
| + base::Bind( |
| + NotifyWorkerContextStarted, worker_process_id, worker_route_id)); |
| + return; |
| + } |
| + EmbeddedWorkerDevToolsManager::GetInstance()->WorkerContextStarted( |
| + worker_process_id, worker_route_id); |
| +} |
| + |
| +void NotifyWorkerDestroyed(int worker_process_id, int worker_route_id) { |
| + if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| + BrowserThread::PostTask( |
| + BrowserThread::UI, |
| + FROM_HERE, |
| + base::Bind(NotifyWorkerDestroyed, worker_process_id, worker_route_id)); |
| + return; |
| + } |
| + EmbeddedWorkerDevToolsManager::GetInstance()->WorkerDestroyed( |
| + worker_process_id, worker_route_id); |
| +} |
| + |
| +void RegisterToWorkerDevToolsManager( |
| + int process_id, |
| + const base::FilePath& storage_partition_path, |
| + const GURL& scope, |
| + const base::Callback<void(int worker_devtools_agent_route_id, |
| + bool pause_on_start)>& callback) { |
| + if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| + BrowserThread::PostTask(BrowserThread::UI, |
| + FROM_HERE, |
| + base::Bind(RegisterToWorkerDevToolsManager, |
| + process_id, |
| + storage_partition_path, |
| + scope, |
| + callback)); |
| + return; |
| + } |
| + int worker_devtools_agent_route_id = MSG_ROUTING_NONE; |
| + bool pause_on_start = false; |
| + if (RenderProcessHost* rph = RenderProcessHost::FromID(process_id)) { |
| + // |rph| may be NULL in unit tests. |
| + worker_devtools_agent_route_id = rph->GetNextRoutingID(); |
| + pause_on_start = |
| + EmbeddedWorkerDevToolsManager::GetInstance()->ServiceWorkerCreated( |
| + process_id, |
| + worker_devtools_agent_route_id, |
| + storage_partition_path, |
| + scope); |
| + } |
| + BrowserThread::PostTask( |
| + BrowserThread::IO, |
| + FROM_HERE, |
| + base::Bind(callback, worker_devtools_agent_route_id, pause_on_start)); |
| +} |
| + |
| } // namespace |
| EmbeddedWorkerInstance::~EmbeddedWorkerInstance() { |
| + if (worker_devtools_agent_route_id_ != MSG_ROUTING_NONE) |
| + NotifyWorkerDestroyed(process_id_, worker_devtools_agent_route_id_); |
| registry_->RemoveWorker(process_id_, embedded_worker_id_); |
| } |
| void EmbeddedWorkerInstance::Start(int64 service_worker_version_id, |
| - const GURL& scope, |
| const GURL& script_url, |
| const std::vector<int>& possible_process_ids, |
| const StatusCallback& callback) { |
| + if (!context_) { |
| + callback.Run(SERVICE_WORKER_ERROR_ABORT); |
| + return; |
| + } |
| DCHECK(status_ == STOPPED); |
| status_ = STARTING; |
| - std::vector<int> ordered_process_ids = SortProcesses(possible_process_ids); |
| - registry_->StartWorker(ordered_process_ids, |
| - embedded_worker_id_, |
| - service_worker_version_id, |
| - scope, |
| - script_url, |
| - callback); |
| + scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params( |
| + new EmbeddedWorkerMsg_StartWorker_Params()); |
| + params->embedded_worker_id = embedded_worker_id_; |
| + params->service_worker_version_id = service_worker_version_id; |
| + params->scope = scope_; |
| + params->script_url = script_url; |
| + params->worker_devtools_agent_route_id = MSG_ROUTING_NONE; |
| + params->pause_on_start = false; |
| + context_->process_manager()->AllocateWorkerProcess( |
| + SortProcesses(possible_process_ids), |
| + script_url, |
| + base::Bind(&EmbeddedWorkerInstance::RunProcessAllocated, |
| + weak_factory_.GetWeakPtr(), |
| + context_, |
| + base::Passed(¶ms), |
| + callback)); |
| } |
| ServiceWorkerStatusCode EmbeddedWorkerInstance::Stop() { |
| DCHECK(status_ == STARTING || status_ == RUNNING); |
| + if (context_) |
| + context_->process_manager()->ReleaseWorkerProcess(process_id_); |
|
kinuko
2014/05/13 16:25:14
I wonder this should probably be in OnStopped and
horo
2014/05/14 05:09:59
Done.
|
| ServiceWorkerStatusCode status = |
| registry_->StopWorker(process_id_, embedded_worker_id_); |
| if (status == SERVICE_WORKER_OK) |
| @@ -75,32 +157,90 @@ void EmbeddedWorkerInstance::ReleaseProcessReference(int process_id) { |
| process_refs_.erase(found); |
| } |
| -EmbeddedWorkerInstance::EmbeddedWorkerInstance(EmbeddedWorkerRegistry* registry, |
| - int embedded_worker_id) |
| - : registry_(registry), |
| +EmbeddedWorkerInstance::EmbeddedWorkerInstance( |
| + base::WeakPtr<ServiceWorkerContextCore> context, |
| + int embedded_worker_id, |
| + const GURL& scope) |
| + : context_(context), |
| + registry_(context->embedded_worker_registry()), |
| embedded_worker_id_(embedded_worker_id), |
| + scope_(scope), |
| status_(STOPPED), |
| process_id_(-1), |
| thread_id_(-1), |
| - worker_devtools_agent_route_id_(MSG_ROUTING_NONE) { |
| + worker_devtools_agent_route_id_(MSG_ROUTING_NONE), |
| + weak_factory_(this) { |
| } |
| -void EmbeddedWorkerInstance::RecordProcessId( |
| - int process_id, |
| +// static |
| +void EmbeddedWorkerInstance::RunProcessAllocated( |
| + base::WeakPtr<EmbeddedWorkerInstance> instance, |
| + base::WeakPtr<ServiceWorkerContextCore> context, |
| + scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params, |
| + const EmbeddedWorkerInstance::StatusCallback& callback, |
| ServiceWorkerStatusCode status, |
| - int worker_devtools_agent_route_id) { |
| + int process_id) { |
| + if (!context) { |
| + callback.Run(SERVICE_WORKER_ERROR_ABORT); |
| + return; |
| + } |
| + if (!instance) { |
| + context->process_manager()->ReleaseWorkerProcess(process_id); |
| + callback.Run(SERVICE_WORKER_ERROR_ABORT); |
| + return; |
| + } |
| + instance->ProcessAllocated(params.Pass(), callback, process_id, status); |
| +} |
| + |
| +void EmbeddedWorkerInstance::ProcessAllocated( |
| + scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params, |
| + const StatusCallback& callback, |
| + int process_id, |
| + ServiceWorkerStatusCode status) { |
| DCHECK_EQ(process_id_, -1); |
| - DCHECK_EQ(worker_devtools_agent_route_id_, MSG_ROUTING_NONE); |
| - if (status == SERVICE_WORKER_OK) { |
| - process_id_ = process_id; |
| - worker_devtools_agent_route_id_ = worker_devtools_agent_route_id; |
| - } else { |
| + if (status != SERVICE_WORKER_OK) { |
| status_ = STOPPED; |
| + callback.Run(status); |
| + return; |
| + } |
| + process_id_ = process_id; |
| + RegisterToWorkerDevToolsManager( |
| + process_id, |
| + context_->storage_partition_path(), |
| + scope_, |
| + base::Bind(&EmbeddedWorkerInstance::RunSendStartWorker, |
| + weak_factory_.GetWeakPtr(), |
| + base::Passed(¶ms), |
| + callback)); |
| +} |
| + |
| +// static |
| +void EmbeddedWorkerInstance::RunSendStartWorker( |
|
kinuko
2014/05/13 16:25:14
I think we can likely remove this intermediate sta
horo
2014/05/14 05:09:59
Done.
|
| + base::WeakPtr<EmbeddedWorkerInstance> instance, |
| + scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params, |
| + const EmbeddedWorkerInstance::StatusCallback& callback, |
| + int worker_devtools_agent_route_id, |
| + bool pause_on_start) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| + if (!instance) { |
| + callback.Run(SERVICE_WORKER_ERROR_ABORT); |
| + return; |
| } |
| + params->worker_devtools_agent_route_id = worker_devtools_agent_route_id; |
| + params->pause_on_start = pause_on_start; |
| + instance->SendStartWorker(params.Pass(), callback); |
| +} |
| + |
| +void EmbeddedWorkerInstance::SendStartWorker( |
| + scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params, |
| + const StatusCallback& callback) { |
| + worker_devtools_agent_route_id_ = params->worker_devtools_agent_route_id; |
| + registry_->SendStartWorker(params.Pass(), callback, process_id_); |
| } |
| void EmbeddedWorkerInstance::OnScriptLoaded() { |
| - // TODO(horo): Implement this. |
| + if (worker_devtools_agent_route_id_ != MSG_ROUTING_NONE) |
| + NotifyWorkerContextStarted(process_id_, worker_devtools_agent_route_id_); |
| } |
| void EmbeddedWorkerInstance::OnScriptLoadFailed() { |
| @@ -117,6 +257,8 @@ void EmbeddedWorkerInstance::OnStarted(int thread_id) { |
| } |
| void EmbeddedWorkerInstance::OnStopped() { |
| + if (worker_devtools_agent_route_id_ != MSG_ROUTING_NONE) |
| + NotifyWorkerDestroyed(process_id_, worker_devtools_agent_route_id_); |
| status_ = STOPPED; |
| process_id_ = -1; |
| thread_id_ = -1; |