Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / browser / devtools / embedded_worker_devtools_agent_host.cc
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.
4
5 #include "content/browser/devtools/embedded_worker_devtools_agent_host.h"
6
7 #include "base/strings/utf_string_conversions.h"
8 #include "content/browser/devtools/devtools_protocol.h"
9 #include "content/browser/devtools/devtools_protocol_constants.h"
10 #include "content/browser/service_worker/service_worker_context_core.h"
11 #include "content/browser/service_worker/service_worker_version.h"
12 #include "content/browser/shared_worker/shared_worker_service_impl.h"
13 #include "content/common/devtools_messages.h"
14 #include "content/public/browser/browser_thread.h"
15 #include "content/public/browser/render_process_host.h"
16
17 namespace content {
18
19 namespace {
20
21 void TerminateSharedWorkerOnIO(
22     EmbeddedWorkerDevToolsAgentHost::WorkerId worker_id) {
23   SharedWorkerServiceImpl::GetInstance()->TerminateWorker(
24       worker_id.first, worker_id.second);
25 }
26
27 void StatusNoOp(ServiceWorkerStatusCode status) {
28 }
29
30 void TerminateServiceWorkerOnIO(
31     base::WeakPtr<ServiceWorkerContextCore> context_weak,
32     int64 version_id) {
33   if (ServiceWorkerContextCore* context = context_weak.get()) {
34     if (ServiceWorkerVersion* version = context->GetLiveVersion(version_id))
35       version->StopWorker(base::Bind(&StatusNoOp));
36   }
37 }
38
39 }
40
41 EmbeddedWorkerDevToolsAgentHost::EmbeddedWorkerDevToolsAgentHost(
42     WorkerId worker_id,
43     const SharedWorkerInstance& shared_worker)
44     : shared_worker_(new SharedWorkerInstance(shared_worker)),
45       state_(WORKER_UNINSPECTED),
46       worker_id_(worker_id) {
47   WorkerCreated();
48 }
49
50 EmbeddedWorkerDevToolsAgentHost::EmbeddedWorkerDevToolsAgentHost(
51     WorkerId worker_id,
52     const ServiceWorkerIdentifier& service_worker,
53     bool debug_service_worker_on_start)
54     : service_worker_(new ServiceWorkerIdentifier(service_worker)),
55       state_(WORKER_UNINSPECTED),
56       worker_id_(worker_id) {
57   if (debug_service_worker_on_start)
58     state_ = WORKER_PAUSED_FOR_DEBUG_ON_START;
59   WorkerCreated();
60 }
61
62 bool EmbeddedWorkerDevToolsAgentHost::IsWorker() const {
63   return true;
64 }
65
66 DevToolsAgentHost::Type EmbeddedWorkerDevToolsAgentHost::GetType() {
67   return shared_worker_ ? TYPE_SHARED_WORKER : TYPE_SERVICE_WORKER;
68 }
69
70 std::string EmbeddedWorkerDevToolsAgentHost::GetTitle() {
71   if (shared_worker_ && shared_worker_->name().length())
72     return base::UTF16ToUTF8(shared_worker_->name());
73   if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id_.first)) {
74     return base::StringPrintf("Worker pid:%d",
75                               base::GetProcId(host->GetHandle()));
76   }
77   return "";
78 }
79
80 GURL EmbeddedWorkerDevToolsAgentHost::GetURL() {
81   if (shared_worker_)
82     return shared_worker_->url();
83   if (service_worker_)
84     return service_worker_->url();
85   return GURL();
86 }
87
88 bool EmbeddedWorkerDevToolsAgentHost::Activate() {
89   return false;
90 }
91
92 bool EmbeddedWorkerDevToolsAgentHost::Close() {
93   if (shared_worker_) {
94     BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
95         base::Bind(&TerminateSharedWorkerOnIO, worker_id_));
96     return true;
97   }
98   if (service_worker_) {
99     BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
100         base::Bind(&TerminateServiceWorkerOnIO,
101                    service_worker_->context_weak(),
102                    service_worker_->version_id()));
103     return true;
104   }
105   return false;
106 }
107
108 void EmbeddedWorkerDevToolsAgentHost::SendMessageToAgent(
109     IPC::Message* message_raw) {
110   scoped_ptr<IPC::Message> message(message_raw);
111   if (state_ != WORKER_INSPECTED)
112     return;
113   if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id_.first)) {
114     message->set_routing_id(worker_id_.second);
115     host->Send(message.release());
116   }
117 }
118
119 void EmbeddedWorkerDevToolsAgentHost::Attach() {
120   if (state_ != WORKER_INSPECTED) {
121     state_ = WORKER_INSPECTED;
122     AttachToWorker();
123   }
124   IPCDevToolsAgentHost::Attach();
125 }
126
127 void EmbeddedWorkerDevToolsAgentHost::OnClientDetached() {
128   if (state_ == WORKER_INSPECTED) {
129     state_ = WORKER_UNINSPECTED;
130     DetachFromWorker();
131   } else if (state_ == WORKER_PAUSED_FOR_REATTACH) {
132     state_ = WORKER_UNINSPECTED;
133   }
134 }
135
136 bool EmbeddedWorkerDevToolsAgentHost::OnMessageReceived(
137     const IPC::Message& msg) {
138   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
139   bool handled = true;
140   IPC_BEGIN_MESSAGE_MAP(EmbeddedWorkerDevToolsAgentHost, msg)
141   IPC_MESSAGE_HANDLER(DevToolsClientMsg_DispatchOnInspectorFrontend,
142                       OnDispatchOnInspectorFrontend)
143   IPC_MESSAGE_HANDLER(DevToolsHostMsg_SaveAgentRuntimeState,
144                       OnSaveAgentRuntimeState)
145   IPC_MESSAGE_UNHANDLED(handled = false)
146   IPC_END_MESSAGE_MAP()
147   return handled;
148 }
149
150 void EmbeddedWorkerDevToolsAgentHost::WorkerReadyForInspection() {
151   if (state_ == WORKER_PAUSED_FOR_DEBUG_ON_START) {
152     RenderProcessHost* rph = RenderProcessHost::FromID(worker_id_.first);
153     Inspect(rph->GetBrowserContext());
154   } else if (state_ == WORKER_PAUSED_FOR_REATTACH) {
155     DCHECK(IsAttached());
156     state_ = WORKER_INSPECTED;
157     AttachToWorker();
158     Reattach(saved_agent_state_);
159   }
160 }
161
162 void EmbeddedWorkerDevToolsAgentHost::WorkerRestarted(WorkerId worker_id) {
163   DCHECK_EQ(WORKER_TERMINATED, state_);
164   state_ = IsAttached() ? WORKER_PAUSED_FOR_REATTACH : WORKER_UNINSPECTED;
165   worker_id_ = worker_id;
166   WorkerCreated();
167 }
168
169 void EmbeddedWorkerDevToolsAgentHost::WorkerDestroyed() {
170   DCHECK_NE(WORKER_TERMINATED, state_);
171   if (state_ == WORKER_INSPECTED) {
172     DCHECK(IsAttached());
173     // Client host is debugging this worker agent host.
174     std::string notification =
175         DevToolsProtocol::CreateNotification(
176             devtools::Worker::disconnectedFromWorker::kName, NULL)->Serialize();
177     SendMessageToClient(notification);
178     DetachFromWorker();
179   }
180   state_ = WORKER_TERMINATED;
181   Release();  // Balanced in WorkerCreated()
182 }
183
184 bool EmbeddedWorkerDevToolsAgentHost::Matches(
185     const SharedWorkerInstance& other) {
186   return shared_worker_ && shared_worker_->Matches(other);
187 }
188
189 bool EmbeddedWorkerDevToolsAgentHost::Matches(
190     const ServiceWorkerIdentifier& other) {
191   return service_worker_ && service_worker_->Matches(other);
192 }
193
194 bool EmbeddedWorkerDevToolsAgentHost::IsTerminated() {
195   return state_ == WORKER_TERMINATED;
196 }
197
198 EmbeddedWorkerDevToolsAgentHost::~EmbeddedWorkerDevToolsAgentHost() {
199   DCHECK_EQ(WORKER_TERMINATED, state_);
200   EmbeddedWorkerDevToolsManager::GetInstance()->RemoveInspectedWorkerData(
201       worker_id_);
202 }
203
204 void EmbeddedWorkerDevToolsAgentHost::AttachToWorker() {
205   if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id_.first))
206     host->AddRoute(worker_id_.second, this);
207 }
208
209 void EmbeddedWorkerDevToolsAgentHost::DetachFromWorker() {
210   if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id_.first))
211     host->RemoveRoute(worker_id_.second);
212 }
213
214 void EmbeddedWorkerDevToolsAgentHost::WorkerCreated() {
215   AddRef();  // Balanced in WorkerDestroyed()
216 }
217
218 void EmbeddedWorkerDevToolsAgentHost::OnDispatchOnInspectorFrontend(
219     const std::string& message,
220     uint32 total_size) {
221   if (!IsAttached())
222     return;
223
224   ProcessChunkedMessageFromAgent(message, total_size);
225 }
226
227 void EmbeddedWorkerDevToolsAgentHost::OnSaveAgentRuntimeState(
228     const std::string& state) {
229   saved_agent_state_ = state;
230 }
231
232 }  // namespace content