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/devtools_manager.h"
8 #include "content/browser/devtools/ipc_devtools_agent_host.h"
9 #include "content/browser/devtools/service_worker_devtools_agent_host.h"
10 #include "content/public/browser/browser_thread.h"
11 #include "content/public/browser/render_process_host.h"
12 #include "content/public/browser/worker_service.h"
13 #include "ipc/ipc_listener.h"
17 ServiceWorkerDevToolsManager::ServiceWorkerIdentifier::ServiceWorkerIdentifier(
18 const ServiceWorkerContextCore
* context
,
19 base::WeakPtr
<ServiceWorkerContextCore
> context_weak
,
23 context_weak_(context_weak
),
24 version_id_(version_id
),
28 ServiceWorkerDevToolsManager::ServiceWorkerIdentifier::ServiceWorkerIdentifier(
29 const ServiceWorkerIdentifier
& other
)
30 : context_(other
.context_
),
31 context_weak_(other
.context_weak_
),
32 version_id_(other
.version_id_
),
36 ServiceWorkerDevToolsManager::
37 ServiceWorkerIdentifier::~ServiceWorkerIdentifier() {
40 bool ServiceWorkerDevToolsManager::ServiceWorkerIdentifier::Matches(
41 const ServiceWorkerIdentifier
& other
) const {
42 return context_
== other
.context_
&& version_id_
== other
.version_id_
;
46 ServiceWorkerDevToolsManager
* ServiceWorkerDevToolsManager::GetInstance() {
47 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
48 return Singleton
<ServiceWorkerDevToolsManager
>::get();
51 DevToolsAgentHostImpl
*
52 ServiceWorkerDevToolsManager::GetDevToolsAgentHostForWorker(
53 int worker_process_id
,
54 int worker_route_id
) {
55 AgentHostMap::iterator it
= workers_
.find(
56 WorkerId(worker_process_id
, worker_route_id
));
57 return it
== workers_
.end() ? NULL
: it
->second
;
60 void ServiceWorkerDevToolsManager::AddAllAgentHosts(
61 ServiceWorkerDevToolsAgentHost::List
* result
) {
62 for (auto& worker
: workers_
) {
63 if (!worker
.second
->IsTerminated())
64 result
->push_back(worker
.second
);
68 bool ServiceWorkerDevToolsManager::WorkerCreated(
69 int worker_process_id
,
71 const ServiceWorkerIdentifier
& service_worker_id
) {
72 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
73 const WorkerId
id(worker_process_id
, worker_route_id
);
74 AgentHostMap::iterator it
= FindExistingWorkerAgentHost(service_worker_id
);
75 if (it
== workers_
.end()) {
76 scoped_refptr
<ServiceWorkerDevToolsAgentHost
> host
=
77 new ServiceWorkerDevToolsAgentHost(
78 id
, service_worker_id
);
79 workers_
[id
] = host
.get();
80 FOR_EACH_OBSERVER(Observer
, observer_list_
, WorkerCreated(host
.get()));
81 DevToolsManager::GetInstance()->AgentHostChanged(host
.get());
82 if (debug_service_worker_on_start_
)
83 host
->PauseForDebugOnStart();
84 return host
->IsPausedForDebugOnStart();
87 // Worker was restarted.
88 ServiceWorkerDevToolsAgentHost
* agent_host
= it
->second
;
89 agent_host
->WorkerRestarted(id
);
91 workers_
[id
] = agent_host
;
92 DevToolsManager::GetInstance()->AgentHostChanged(agent_host
);
94 return it
->second
->IsAttached();
97 void ServiceWorkerDevToolsManager::WorkerReadyForInspection(
98 int worker_process_id
,
99 int worker_route_id
) {
100 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
101 const WorkerId
id(worker_process_id
, worker_route_id
);
102 AgentHostMap::iterator it
= workers_
.find(id
);
103 DCHECK(it
!= workers_
.end());
104 scoped_refptr
<ServiceWorkerDevToolsAgentHost
> host
= it
->second
;
105 host
->WorkerReadyForInspection();
106 FOR_EACH_OBSERVER(Observer
, observer_list_
,
107 WorkerReadyForInspection(host
.get()));
109 // Then bring up UI for the ones not picked by other clients.
110 if (host
->IsPausedForDebugOnStart() && !host
->IsAttached()) {
111 host
->Inspect(RenderProcessHost::FromID(worker_process_id
)->
112 GetBrowserContext());
116 void ServiceWorkerDevToolsManager::WorkerStopIgnored(int worker_process_id
,
117 int worker_route_id
) {
118 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
119 // TODO(pfeldman): Show a console message to tell the user that UA didn't
120 // terminate the worker because devtools is attached.
123 void ServiceWorkerDevToolsManager::WorkerDestroyed(int worker_process_id
,
124 int worker_route_id
) {
125 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
126 const WorkerId
id(worker_process_id
, worker_route_id
);
127 AgentHostMap::iterator it
= workers_
.find(id
);
128 DCHECK(it
!= workers_
.end());
129 scoped_refptr
<WorkerDevToolsAgentHost
> agent_host(it
->second
);
130 agent_host
->WorkerDestroyed();
131 DevToolsManager::GetInstance()->AgentHostChanged(agent_host
);
132 FOR_EACH_OBSERVER(Observer
, observer_list_
, WorkerDestroyed(it
->second
));
135 void ServiceWorkerDevToolsManager::RemoveInspectedWorkerData(WorkerId id
) {
136 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
140 void ServiceWorkerDevToolsManager::AddObserver(Observer
* observer
) {
141 observer_list_
.AddObserver(observer
);
144 void ServiceWorkerDevToolsManager::RemoveObserver(Observer
* observer
) {
145 observer_list_
.RemoveObserver(observer
);
148 void ServiceWorkerDevToolsManager::set_debug_service_worker_on_start(
149 bool debug_on_start
) {
150 debug_service_worker_on_start_
= debug_on_start
;
151 FOR_EACH_OBSERVER(Observer
, observer_list_
,
152 DebugOnStartUpdated(debug_on_start
));
155 ServiceWorkerDevToolsManager::ServiceWorkerDevToolsManager()
156 : debug_service_worker_on_start_(false) {
159 ServiceWorkerDevToolsManager::~ServiceWorkerDevToolsManager() {
162 ServiceWorkerDevToolsManager::AgentHostMap::iterator
163 ServiceWorkerDevToolsManager::FindExistingWorkerAgentHost(
164 const ServiceWorkerIdentifier
& service_worker_id
) {
165 AgentHostMap::iterator it
= workers_
.begin();
166 for (; it
!= workers_
.end(); ++it
) {
167 if (static_cast<ServiceWorkerDevToolsAgentHost
*>(
168 it
->second
)->Matches(service_worker_id
))
174 void ServiceWorkerDevToolsManager::ResetForTesting() {
178 } // namespace content