1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/devtools/service_worker_devtools_manager.h"
7 #include "content/browser/devtools/service_worker_devtools_agent_host.h"
8 #include "content/public/browser/browser_thread.h"
9 #include "content/public/browser/render_process_host.h"
10 #include "content/public/browser/worker_service.h"
11 #include "ipc/ipc_listener.h"
15 ServiceWorkerDevToolsManager::ServiceWorkerIdentifier::ServiceWorkerIdentifier(
16 const ServiceWorkerContextCore
* context
,
17 base::WeakPtr
<ServiceWorkerContextCore
> context_weak
,
21 context_weak_(context_weak
),
22 version_id_(version_id
),
26 ServiceWorkerDevToolsManager::ServiceWorkerIdentifier::ServiceWorkerIdentifier(
27 const ServiceWorkerIdentifier
& other
)
28 : context_(other
.context_
),
29 context_weak_(other
.context_weak_
),
30 version_id_(other
.version_id_
),
34 ServiceWorkerDevToolsManager::
35 ServiceWorkerIdentifier::~ServiceWorkerIdentifier() {
38 bool ServiceWorkerDevToolsManager::ServiceWorkerIdentifier::Matches(
39 const ServiceWorkerIdentifier
& other
) const {
40 return context_
== other
.context_
&& version_id_
== other
.version_id_
;
44 ServiceWorkerDevToolsManager
* ServiceWorkerDevToolsManager::GetInstance() {
45 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
46 return Singleton
<ServiceWorkerDevToolsManager
>::get();
49 DevToolsAgentHostImpl
*
50 ServiceWorkerDevToolsManager::GetDevToolsAgentHostForWorker(
51 int worker_process_id
,
52 int worker_route_id
) {
53 AgentHostMap::iterator it
= workers_
.find(
54 WorkerId(worker_process_id
, worker_route_id
));
55 return it
== workers_
.end() ? NULL
: it
->second
;
58 void ServiceWorkerDevToolsManager::AddAllAgentHosts(
59 ServiceWorkerDevToolsAgentHost::List
* result
) {
60 for (auto& worker
: workers_
) {
61 if (!worker
.second
->IsTerminated())
62 result
->push_back(worker
.second
);
66 void ServiceWorkerDevToolsManager::AddAllAgentHostsForBrowserContext(
67 BrowserContext
* browser_context
,
68 ServiceWorkerDevToolsAgentHost::List
* result
) {
69 for (auto& worker
: workers_
) {
70 if (!worker
.second
->IsTerminated() &&
71 worker
.second
->GetBrowserContext() == browser_context
) {
72 result
->push_back(worker
.second
);
77 bool ServiceWorkerDevToolsManager::WorkerCreated(
78 int worker_process_id
,
80 const ServiceWorkerIdentifier
& service_worker_id
) {
81 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
82 const WorkerId
id(worker_process_id
, worker_route_id
);
83 AgentHostMap::iterator it
= FindExistingWorkerAgentHost(service_worker_id
);
84 if (it
== workers_
.end()) {
85 scoped_refptr
<ServiceWorkerDevToolsAgentHost
> host
=
86 new ServiceWorkerDevToolsAgentHost(
87 id
, service_worker_id
);
88 workers_
[id
] = host
.get();
89 FOR_EACH_OBSERVER(Observer
, observer_list_
, WorkerCreated(host
.get()));
90 if (debug_service_worker_on_start_
)
91 host
->PauseForDebugOnStart();
92 return host
->IsPausedForDebugOnStart();
95 // Worker was restarted.
96 ServiceWorkerDevToolsAgentHost
* agent_host
= it
->second
;
97 agent_host
->WorkerRestarted(id
);
99 workers_
[id
] = agent_host
;
101 return agent_host
->IsAttached();
104 void ServiceWorkerDevToolsManager::WorkerReadyForInspection(
105 int worker_process_id
,
106 int worker_route_id
) {
107 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
108 const WorkerId
id(worker_process_id
, worker_route_id
);
109 AgentHostMap::iterator it
= workers_
.find(id
);
110 DCHECK(it
!= workers_
.end());
111 scoped_refptr
<ServiceWorkerDevToolsAgentHost
> host
= it
->second
;
112 host
->WorkerReadyForInspection();
113 FOR_EACH_OBSERVER(Observer
, observer_list_
,
114 WorkerReadyForInspection(host
.get()));
116 // Then bring up UI for the ones not picked by other clients.
117 if (host
->IsPausedForDebugOnStart() && !host
->IsAttached()) {
118 host
->Inspect(RenderProcessHost::FromID(worker_process_id
)->
119 GetBrowserContext());
123 void ServiceWorkerDevToolsManager::WorkerStopIgnored(int worker_process_id
,
124 int worker_route_id
) {
125 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
126 // TODO(pfeldman): Show a console message to tell the user that UA didn't
127 // terminate the worker because devtools is attached.
130 void ServiceWorkerDevToolsManager::WorkerDestroyed(int worker_process_id
,
131 int worker_route_id
) {
132 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
133 const WorkerId
id(worker_process_id
, worker_route_id
);
134 AgentHostMap::iterator it
= workers_
.find(id
);
135 DCHECK(it
!= workers_
.end());
136 scoped_refptr
<WorkerDevToolsAgentHost
> agent_host(it
->second
);
137 agent_host
->WorkerDestroyed();
138 FOR_EACH_OBSERVER(Observer
, observer_list_
, WorkerDestroyed(it
->second
));
141 void ServiceWorkerDevToolsManager::RemoveInspectedWorkerData(WorkerId id
) {
142 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
146 void ServiceWorkerDevToolsManager::AddObserver(Observer
* observer
) {
147 observer_list_
.AddObserver(observer
);
150 void ServiceWorkerDevToolsManager::RemoveObserver(Observer
* observer
) {
151 observer_list_
.RemoveObserver(observer
);
154 void ServiceWorkerDevToolsManager::set_debug_service_worker_on_start(
155 bool debug_on_start
) {
156 debug_service_worker_on_start_
= debug_on_start
;
157 FOR_EACH_OBSERVER(Observer
, observer_list_
,
158 DebugOnStartUpdated(debug_on_start
));
161 ServiceWorkerDevToolsManager::ServiceWorkerDevToolsManager()
162 : debug_service_worker_on_start_(false) {
165 ServiceWorkerDevToolsManager::~ServiceWorkerDevToolsManager() {
168 ServiceWorkerDevToolsManager::AgentHostMap::iterator
169 ServiceWorkerDevToolsManager::FindExistingWorkerAgentHost(
170 const ServiceWorkerIdentifier
& service_worker_id
) {
171 AgentHostMap::iterator it
= workers_
.begin();
172 for (; it
!= workers_
.end(); ++it
) {
173 if (static_cast<ServiceWorkerDevToolsAgentHost
*>(
174 it
->second
)->Matches(service_worker_id
))
180 void ServiceWorkerDevToolsManager::ResetForTesting() {
184 } // namespace content