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/embedded_worker_devtools_agent_host.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "content/browser/devtools/devtools_manager_impl.h"
9 #include "content/browser/devtools/devtools_protocol.h"
10 #include "content/browser/devtools/devtools_protocol_constants.h"
11 #include "content/browser/service_worker/service_worker_context_core.h"
12 #include "content/browser/service_worker/service_worker_version.h"
13 #include "content/browser/shared_worker/shared_worker_service_impl.h"
14 #include "content/common/devtools_messages.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "content/public/browser/render_process_host.h"
22 void TerminateSharedWorkerOnIO(
23 EmbeddedWorkerDevToolsAgentHost::WorkerId worker_id
) {
24 SharedWorkerServiceImpl::GetInstance()->TerminateWorker(
25 worker_id
.first
, worker_id
.second
);
28 void StatusNoOp(ServiceWorkerStatusCode status
) {
31 void TerminateServiceWorkerOnIO(
32 base::WeakPtr
<ServiceWorkerContextCore
> context_weak
,
34 if (ServiceWorkerContextCore
* context
= context_weak
.get()) {
35 if (ServiceWorkerVersion
* version
= context
->GetLiveVersion(version_id
))
36 version
->StopWorker(base::Bind(&StatusNoOp
));
42 EmbeddedWorkerDevToolsAgentHost::EmbeddedWorkerDevToolsAgentHost(
44 const SharedWorkerInstance
& shared_worker
)
45 : shared_worker_(new SharedWorkerInstance(shared_worker
)),
46 state_(WORKER_UNINSPECTED
),
47 worker_id_(worker_id
) {
51 EmbeddedWorkerDevToolsAgentHost::EmbeddedWorkerDevToolsAgentHost(
53 const ServiceWorkerIdentifier
& service_worker
,
54 bool debug_service_worker_on_start
)
55 : service_worker_(new ServiceWorkerIdentifier(service_worker
)),
56 state_(WORKER_UNINSPECTED
),
57 worker_id_(worker_id
) {
58 if (debug_service_worker_on_start
)
59 state_
= WORKER_PAUSED_FOR_DEBUG_ON_START
;
63 bool EmbeddedWorkerDevToolsAgentHost::IsWorker() const {
67 DevToolsAgentHost::Type
EmbeddedWorkerDevToolsAgentHost::GetType() {
68 return shared_worker_
? TYPE_SHARED_WORKER
: TYPE_SERVICE_WORKER
;
71 std::string
EmbeddedWorkerDevToolsAgentHost::GetTitle() {
72 return shared_worker_
? base::UTF16ToUTF8(shared_worker_
->name()) : "";
75 GURL
EmbeddedWorkerDevToolsAgentHost::GetURL() {
77 return shared_worker_
->url();
79 return service_worker_
->url();
83 bool EmbeddedWorkerDevToolsAgentHost::Activate() {
87 bool EmbeddedWorkerDevToolsAgentHost::Close() {
89 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
90 base::Bind(&TerminateSharedWorkerOnIO
, worker_id_
));
93 if (service_worker_
) {
94 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
95 base::Bind(&TerminateServiceWorkerOnIO
,
96 service_worker_
->context_weak(),
97 service_worker_
->version_id()));
103 void EmbeddedWorkerDevToolsAgentHost::SendMessageToAgent(
104 IPC::Message
* message_raw
) {
105 scoped_ptr
<IPC::Message
> message(message_raw
);
106 if (state_
!= WORKER_INSPECTED
)
108 if (RenderProcessHost
* host
= RenderProcessHost::FromID(worker_id_
.first
)) {
109 message
->set_routing_id(worker_id_
.second
);
110 host
->Send(message
.release());
114 void EmbeddedWorkerDevToolsAgentHost::Attach() {
115 if (state_
!= WORKER_INSPECTED
) {
116 state_
= WORKER_INSPECTED
;
119 IPCDevToolsAgentHost::Attach();
122 void EmbeddedWorkerDevToolsAgentHost::OnClientDetached() {
123 if (state_
== WORKER_INSPECTED
) {
124 state_
= WORKER_UNINSPECTED
;
126 } else if (state_
== WORKER_PAUSED_FOR_REATTACH
) {
127 state_
= WORKER_UNINSPECTED
;
131 bool EmbeddedWorkerDevToolsAgentHost::OnMessageReceived(
132 const IPC::Message
& msg
) {
133 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
135 IPC_BEGIN_MESSAGE_MAP(EmbeddedWorkerDevToolsAgentHost
, msg
)
136 IPC_MESSAGE_HANDLER(DevToolsClientMsg_DispatchOnInspectorFrontend
,
137 OnDispatchOnInspectorFrontend
)
138 IPC_MESSAGE_HANDLER(DevToolsHostMsg_SaveAgentRuntimeState
,
139 OnSaveAgentRuntimeState
)
140 IPC_MESSAGE_UNHANDLED(handled
= false)
141 IPC_END_MESSAGE_MAP()
145 void EmbeddedWorkerDevToolsAgentHost::WorkerReadyForInspection() {
146 if (state_
== WORKER_PAUSED_FOR_DEBUG_ON_START
) {
147 RenderProcessHost
* rph
= RenderProcessHost::FromID(worker_id_
.first
);
148 Inspect(rph
->GetBrowserContext());
149 } else if (state_
== WORKER_PAUSED_FOR_REATTACH
) {
150 DCHECK(IsAttached());
151 state_
= WORKER_INSPECTED
;
153 Reattach(saved_agent_state_
);
157 void EmbeddedWorkerDevToolsAgentHost::WorkerContextStarted() {
160 void EmbeddedWorkerDevToolsAgentHost::WorkerRestarted(WorkerId worker_id
) {
161 DCHECK_EQ(WORKER_TERMINATED
, state_
);
162 state_
= IsAttached() ? WORKER_PAUSED_FOR_REATTACH
: WORKER_UNINSPECTED
;
163 worker_id_
= worker_id
;
167 void EmbeddedWorkerDevToolsAgentHost::WorkerDestroyed() {
168 DCHECK_NE(WORKER_TERMINATED
, state_
);
169 if (state_
== WORKER_INSPECTED
) {
170 DCHECK(IsAttached());
171 // Client host is debugging this worker agent host.
172 std::string notification
=
173 DevToolsProtocol::CreateNotification(
174 devtools::Worker::disconnectedFromWorker::kName
, NULL
)->Serialize();
175 SendMessageToClient(notification
);
178 state_
= WORKER_TERMINATED
;
179 Release(); // Balanced in WorkerCreated()
182 bool EmbeddedWorkerDevToolsAgentHost::Matches(
183 const SharedWorkerInstance
& other
) {
184 return shared_worker_
&& shared_worker_
->Matches(other
);
187 bool EmbeddedWorkerDevToolsAgentHost::Matches(
188 const ServiceWorkerIdentifier
& other
) {
189 return service_worker_
&& service_worker_
->Matches(other
);
192 bool EmbeddedWorkerDevToolsAgentHost::IsTerminated() {
193 return state_
== WORKER_TERMINATED
;
196 EmbeddedWorkerDevToolsAgentHost::~EmbeddedWorkerDevToolsAgentHost() {
197 DCHECK_EQ(WORKER_TERMINATED
, state_
);
198 EmbeddedWorkerDevToolsManager::GetInstance()->RemoveInspectedWorkerData(
202 void EmbeddedWorkerDevToolsAgentHost::AttachToWorker() {
203 if (RenderProcessHost
* host
= RenderProcessHost::FromID(worker_id_
.first
))
204 host
->AddRoute(worker_id_
.second
, this);
207 void EmbeddedWorkerDevToolsAgentHost::DetachFromWorker() {
208 if (RenderProcessHost
* host
= RenderProcessHost::FromID(worker_id_
.first
))
209 host
->RemoveRoute(worker_id_
.second
);
212 void EmbeddedWorkerDevToolsAgentHost::WorkerCreated() {
213 AddRef(); // Balanced in WorkerDestroyed()
216 void EmbeddedWorkerDevToolsAgentHost::OnDispatchOnInspectorFrontend(
217 const std::string
& message
) {
218 SendMessageToClient(message
);
221 void EmbeddedWorkerDevToolsAgentHost::OnSaveAgentRuntimeState(
222 const std::string
& state
) {
223 saved_agent_state_
= state
;
226 } // namespace content