OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/devtools/devtools_http_handler_impl.h" | |
6 | |
7 #include <algorithm> | 5 #include <algorithm> |
8 #include <utility> | 6 #include <utility> |
9 | 7 |
10 #include "base/bind.h" | 8 #include "base/bind.h" |
11 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
12 #include "base/files/file_util.h" | 10 #include "base/files/file_util.h" |
13 #include "base/json/json_writer.h" | 11 #include "base/json/json_writer.h" |
14 #include "base/logging.h" | 12 #include "base/logging.h" |
15 #include "base/message_loop/message_loop_proxy.h" | 13 #include "base/message_loop/message_loop_proxy.h" |
16 #include "base/stl_util.h" | 14 #include "base/stl_util.h" |
17 #include "base/strings/string_number_conversions.h" | 15 #include "base/strings/string_number_conversions.h" |
18 #include "base/threading/thread.h" | 16 #include "base/threading/thread.h" |
19 #include "base/values.h" | 17 #include "base/values.h" |
20 #include "content/browser/devtools/devtools_manager.h" | 18 #include "content/browser/devtools/devtools_manager.h" |
21 #include "content/browser/devtools/devtools_protocol.h" | 19 #include "content/browser/devtools/devtools_protocol.h" |
22 #include "content/browser/devtools/devtools_protocol_constants.h" | 20 #include "content/browser/devtools/devtools_protocol_constants.h" |
23 #include "content/browser/devtools/devtools_system_info_handler.h" | 21 #include "content/browser/devtools/devtools_system_info_handler.h" |
24 #include "content/browser/devtools/protocol/devtools_protocol_handler_impl.h" | 22 #include "content/browser/devtools/protocol/devtools_protocol_handler_impl.h" |
25 #include "content/browser/devtools/protocol/tracing_handler.h" | 23 #include "content/browser/devtools/protocol/tracing_handler.h" |
26 #include "content/browser/devtools/tethering_handler.h" | 24 #include "content/browser/devtools/tethering_handler.h" |
27 #include "content/common/devtools_messages.h" | 25 #include "content/common/devtools_messages.h" |
28 #include "content/public/browser/browser_thread.h" | 26 #include "content/public/browser/browser_thread.h" |
29 #include "content/public/browser/devtools_agent_host.h" | 27 #include "content/public/browser/devtools_agent_host.h" |
28 #include "content/public/browser/devtools_http_handler.h" | |
30 #include "content/public/browser/devtools_http_handler_delegate.h" | 29 #include "content/public/browser/devtools_http_handler_delegate.h" |
31 #include "content/public/browser/devtools_target.h" | 30 #include "content/public/browser/devtools_target.h" |
32 #include "content/public/common/content_client.h" | 31 #include "content/public/common/content_client.h" |
33 #include "content/public/common/url_constants.h" | 32 #include "content/public/common/url_constants.h" |
34 #include "content/public/common/user_agent.h" | 33 #include "content/public/common/user_agent.h" |
35 #include "grit/devtools_resources_map.h" | 34 #include "grit/devtools_resources_map.h" |
36 #include "net/base/escape.h" | 35 #include "net/base/escape.h" |
37 #include "net/base/io_buffer.h" | 36 #include "net/base/io_buffer.h" |
38 #include "net/base/ip_endpoint.h" | 37 #include "net/base/ip_endpoint.h" |
39 #include "net/base/net_errors.h" | 38 #include "net/base/net_errors.h" |
39 #include "net/server/http_server.h" | |
40 #include "net/server/http_server_request_info.h" | 40 #include "net/server/http_server_request_info.h" |
41 #include "net/server/http_server_response_info.h" | 41 #include "net/server/http_server_response_info.h" |
42 #include "net/socket/server_socket.h" | 42 #include "net/socket/server_socket.h" |
43 | 43 |
44 #if defined(OS_ANDROID) | 44 #if defined(OS_ANDROID) |
45 #include "base/android/build_info.h" | 45 #include "base/android/build_info.h" |
46 #endif | 46 #endif |
47 | 47 |
48 namespace content { | 48 namespace content { |
49 | 49 |
(...skipping 14 matching lines...) Expand all Loading... | |
64 const char kTargetDescriptionField[] = "description"; | 64 const char kTargetDescriptionField[] = "description"; |
65 const char kTargetUrlField[] = "url"; | 65 const char kTargetUrlField[] = "url"; |
66 const char kTargetThumbnailUrlField[] = "thumbnailUrl"; | 66 const char kTargetThumbnailUrlField[] = "thumbnailUrl"; |
67 const char kTargetFaviconUrlField[] = "faviconUrl"; | 67 const char kTargetFaviconUrlField[] = "faviconUrl"; |
68 const char kTargetWebSocketDebuggerUrlField[] = "webSocketDebuggerUrl"; | 68 const char kTargetWebSocketDebuggerUrlField[] = "webSocketDebuggerUrl"; |
69 const char kTargetDevtoolsFrontendUrlField[] = "devtoolsFrontendUrl"; | 69 const char kTargetDevtoolsFrontendUrlField[] = "devtoolsFrontendUrl"; |
70 | 70 |
71 // Maximum write buffer size of devtools http/websocket connectinos. | 71 // Maximum write buffer size of devtools http/websocket connectinos. |
72 const int32 kSendBufferSizeForDevTools = 100 * 1024 * 1024; // 100Mb | 72 const int32 kSendBufferSizeForDevTools = 100 * 1024 * 1024; // 100Mb |
73 | 73 |
74 class BrowserTarget; | |
75 class DevToolsAgentHostClientImpl; | |
76 class ServerWrapper; | |
77 | |
78 // DevToolsHttpHandlerImpl --------------------------------------------------- | |
79 | |
80 class DevToolsHttpHandlerImpl : public DevToolsHttpHandler { | |
81 public: | |
82 DevToolsHttpHandlerImpl(scoped_ptr<ServerSocketFactory> server_socket_factory, | |
83 const std::string& frontend_url, | |
84 DevToolsHttpHandlerDelegate* delegate, | |
85 const base::FilePath& output_directory); | |
86 ~DevToolsHttpHandlerImpl() override; | |
87 | |
88 void OnJsonRequest(int connection_id, | |
89 const net::HttpServerRequestInfo& info); | |
90 void OnThumbnailRequest(int connection_id, const std::string& target_id); | |
91 void OnDiscoveryPageRequest(int connection_id); | |
92 | |
93 void OnWebSocketRequest(int connection_id, | |
94 const net::HttpServerRequestInfo& info); | |
95 void OnWebSocketMessage(int connection_id, const std::string& data); | |
96 void OnClose(int connection_id); | |
97 | |
98 void OnTargetListReceived( | |
99 int connection_id, | |
100 const std::string& host, | |
101 const DevToolsManagerDelegate::TargetList& targets); | |
102 | |
103 void ServerStarted(base::Thread* thread, | |
104 ServerWrapper* server_wrapper, | |
105 scoped_ptr<net::IPEndPoint> ip_address); | |
106 | |
107 private: | |
108 // DevToolsHttpHandler implementation. | |
109 void Stop() override; | |
110 GURL GetFrontendURL() override; | |
111 | |
112 DevToolsTarget* GetTarget(const std::string& id); | |
113 | |
114 void SendJson(int connection_id, | |
115 net::HttpStatusCode status_code, | |
116 base::Value* value, | |
117 const std::string& message); | |
118 void Send200(int connection_id, | |
119 const std::string& data, | |
120 const std::string& mime_type); | |
121 void Send404(int connection_id); | |
122 void Send500(int connection_id, | |
123 const std::string& message); | |
124 void AcceptWebSocket(int connection_id, | |
125 const net::HttpServerRequestInfo& request); | |
126 | |
127 // Returns the front end url without the host at the beginning. | |
128 std::string GetFrontendURLInternal(const std::string target_id, | |
129 const std::string& host); | |
130 | |
131 base::DictionaryValue* SerializeTarget(const DevToolsTarget& target, | |
132 const std::string& host); | |
133 | |
134 // The thread used by the devtools handler to run server socket. | |
135 base::Thread* thread_; | |
136 | |
137 std::string frontend_url_; | |
138 ServerWrapper* server_wrapper_; | |
139 scoped_ptr<net::IPEndPoint> server_ip_address_; | |
140 typedef std::map<int, DevToolsAgentHostClientImpl*> ConnectionToClientMap; | |
141 ConnectionToClientMap connection_to_client_; | |
142 const scoped_ptr<DevToolsHttpHandlerDelegate> delegate_; | |
143 typedef std::map<std::string, DevToolsTarget*> TargetMap; | |
144 TargetMap target_map_; | |
145 typedef std::map<int, BrowserTarget*> BrowserTargets; | |
146 BrowserTargets browser_targets_; | |
147 base::WeakPtrFactory<DevToolsHttpHandlerImpl> weak_factory_; | |
148 | |
149 DISALLOW_COPY_AND_ASSIGN(DevToolsHttpHandlerImpl); | |
150 }; | |
151 | |
152 // ServerWrapper ------------------------------------------------------------- | |
153 | |
154 class ServerWrapper : net::HttpServer::Delegate { | |
dgozman
2014/11/10 15:39:19
Let's comment that this class lives on handler thr
vkuzkokov
2014/11/11 08:52:05
Done.
| |
155 public: | |
156 ServerWrapper(base::WeakPtr<DevToolsHttpHandlerImpl> handler, | |
157 scoped_ptr<net::ServerSocket> socket, | |
158 const base::FilePath& frontend_dir, | |
159 bool bundles_resources); | |
160 | |
161 int GetLocalAddress(net::IPEndPoint* address); | |
162 | |
163 void AcceptWebSocket(int connection_id, | |
164 const net::HttpServerRequestInfo& request); | |
165 void SendOverWebSocket(int connection_id, const std::string& message); | |
166 void SendResponse(int connection_id, | |
167 const net::HttpServerResponseInfo& response); | |
168 void Send200(int connection_id, | |
169 const std::string& data, | |
170 const std::string& mime_type); | |
171 void Send404(int connection_id); | |
172 void Send500(int connection_id, const std::string& message); | |
173 void Close(int connection_id); | |
174 | |
175 void WriteActivePortToUserProfile(const base::FilePath& output_directory); | |
176 | |
177 virtual ~ServerWrapper() {} | |
178 | |
179 private: | |
180 // net::HttpServer::Delegate implementation. | |
181 void OnConnect(int connection_id) override {} | |
182 void OnHttpRequest(int connection_id, | |
183 const net::HttpServerRequestInfo& info) override; | |
184 void OnWebSocketRequest(int connection_id, | |
185 const net::HttpServerRequestInfo& info) override; | |
186 void OnWebSocketMessage(int connection_id, | |
187 const std::string& data) override; | |
188 void OnClose(int connection_id) override; | |
189 | |
190 base::WeakPtr<DevToolsHttpHandlerImpl> handler_; | |
191 scoped_ptr<net::HttpServer> server_; | |
192 base::FilePath frontend_dir_; | |
193 bool bundles_resources_; | |
194 }; | |
195 | |
196 ServerWrapper::ServerWrapper(base::WeakPtr<DevToolsHttpHandlerImpl> handler, | |
197 scoped_ptr<net::ServerSocket> socket, | |
198 const base::FilePath& frontend_dir, | |
199 bool bundles_resources) | |
200 : handler_(handler), | |
201 server_(new net::HttpServer(socket.Pass(), this)), | |
202 frontend_dir_(frontend_dir), | |
203 bundles_resources_(bundles_resources) { | |
204 } | |
205 | |
206 int ServerWrapper::GetLocalAddress(net::IPEndPoint* address) { | |
207 return server_->GetLocalAddress(address); | |
208 } | |
209 | |
210 void ServerWrapper::AcceptWebSocket(int connection_id, | |
211 const net::HttpServerRequestInfo& request) { | |
212 server_->SetSendBufferSize(connection_id, kSendBufferSizeForDevTools); | |
213 server_->AcceptWebSocket(connection_id, request); | |
214 } | |
215 | |
216 void ServerWrapper::SendOverWebSocket(int connection_id, | |
217 const std::string& message) { | |
218 server_->SendOverWebSocket(connection_id, message); | |
219 } | |
220 | |
221 void ServerWrapper::SendResponse(int connection_id, | |
222 const net::HttpServerResponseInfo& response) { | |
223 server_->SendResponse(connection_id, response); | |
224 } | |
225 | |
226 void ServerWrapper::Send200(int connection_id, | |
227 const std::string& data, | |
228 const std::string& mime_type) { | |
229 server_->Send200(connection_id, data, mime_type); | |
230 } | |
231 | |
232 void ServerWrapper::Send404(int connection_id) { | |
233 server_->Send404(connection_id); | |
234 } | |
235 | |
236 void ServerWrapper::Send500(int connection_id, | |
237 const std::string& message) { | |
238 server_->Send500(connection_id, message); | |
239 } | |
240 | |
241 void ServerWrapper::Close(int connection_id) { | |
242 server_->Close(connection_id); | |
243 } | |
244 | |
245 // Thread and ServerWrapper lifetime management ------------------------------ | |
246 | |
247 void Terminate(base::Thread* thread, ServerWrapper* server_wrapper) { | |
dgozman
2014/11/10 15:39:19
TerminateOnUI
vkuzkokov
2014/11/11 08:52:05
Done.
| |
248 if (server_wrapper) { | |
249 DCHECK(thread); | |
250 thread->message_loop()->DeleteSoon(FROM_HERE, server_wrapper); | |
251 } | |
252 if (thread) { | |
253 BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, thread); | |
254 } | |
255 } | |
256 | |
257 void ServerStartedOnUI( | |
dgozman
2014/11/10 15:39:19
Let's DCHECK that thread is valid in all these sta
vkuzkokov
2014/11/11 08:52:05
Done.
| |
258 base::WeakPtr<DevToolsHttpHandlerImpl> handler, | |
259 base::Thread* thread, | |
260 ServerWrapper* server_wrapper, | |
261 scoped_ptr<net::IPEndPoint> ip_address) { | |
262 if (handler && thread && server_wrapper) { | |
263 handler->ServerStarted(thread, server_wrapper, ip_address.Pass()); | |
264 } else { | |
265 Terminate(thread, server_wrapper); | |
266 } | |
267 } | |
268 | |
269 void StartServerOnHandlerThread( | |
270 base::WeakPtr<DevToolsHttpHandlerImpl> handler, | |
271 base::Thread* thread, | |
272 scoped_ptr<DevToolsHttpHandler::ServerSocketFactory> server_socket_factory, | |
273 const base::FilePath& output_directory, | |
274 const base::FilePath& frontend_dir, | |
275 bool bundles_resources) { | |
276 ServerWrapper* server_wrapper = nullptr; | |
277 scoped_ptr<net::ServerSocket> server_socket = | |
278 server_socket_factory->CreateAndListen(); | |
279 scoped_ptr<net::IPEndPoint> ip_address(new net::IPEndPoint); | |
280 if (server_socket) { | |
281 server_wrapper = new ServerWrapper(handler, server_socket.Pass(), | |
282 frontend_dir, bundles_resources); | |
283 if (!output_directory.empty()) | |
284 server_wrapper->WriteActivePortToUserProfile(output_directory); | |
285 | |
286 if (server_wrapper->GetLocalAddress(ip_address.get()) != net::OK) | |
287 ip_address.reset(); | |
288 } else { | |
289 ip_address.reset(); | |
290 LOG(ERROR) << "Cannot start http server for devtools. Stop devtools."; | |
291 } | |
292 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
293 base::Bind(&ServerStartedOnUI, | |
294 handler, thread, server_wrapper, base::Passed(&ip_address))); | |
295 } | |
296 | |
297 void StartServerOnFile( | |
298 base::WeakPtr<DevToolsHttpHandlerImpl> handler, | |
299 scoped_ptr<DevToolsHttpHandler::ServerSocketFactory> server_socket_factory, | |
300 const base::FilePath& output_directory, | |
301 const base::FilePath& frontend_dir, | |
302 bool bundles_resources) { | |
303 scoped_ptr<base::Thread> thread(new base::Thread(kDevToolsHandlerThreadName)); | |
304 base::Thread::Options options; | |
305 options.message_loop_type = base::MessageLoop::TYPE_IO; | |
306 if (thread->StartWithOptions(options)) { | |
307 base::MessageLoop* message_loop = thread->message_loop(); | |
308 message_loop->PostTask(FROM_HERE, | |
309 base::Bind(&StartServerOnHandlerThread, | |
310 handler, | |
311 base::Unretained(thread.release()), | |
312 base::Passed(&server_socket_factory), | |
313 output_directory, | |
314 frontend_dir, | |
315 bundles_resources)); | |
316 } | |
317 } | |
318 | |
74 // DevToolsAgentHostClientImpl ----------------------------------------------- | 319 // DevToolsAgentHostClientImpl ----------------------------------------------- |
75 | |
76 // An internal implementation of DevToolsAgentHostClient that delegates | 320 // An internal implementation of DevToolsAgentHostClient that delegates |
77 // messages sent to a DebuggerShell instance. | 321 // messages sent to a DebuggerShell instance. |
78 class DevToolsAgentHostClientImpl : public DevToolsAgentHostClient { | 322 class DevToolsAgentHostClientImpl : public DevToolsAgentHostClient { |
79 public: | 323 public: |
80 DevToolsAgentHostClientImpl(base::MessageLoop* message_loop, | 324 DevToolsAgentHostClientImpl(base::MessageLoop* message_loop, |
81 net::HttpServer* server, | 325 ServerWrapper* server_wrapper, |
82 int connection_id, | 326 int connection_id, |
83 DevToolsAgentHost* agent_host) | 327 DevToolsAgentHost* agent_host) |
84 : message_loop_(message_loop), | 328 : message_loop_(message_loop), |
85 server_(server), | 329 server_wrapper_(server_wrapper), |
86 connection_id_(connection_id), | 330 connection_id_(connection_id), |
87 agent_host_(agent_host) { | 331 agent_host_(agent_host) { |
88 agent_host_->AttachClient(this); | 332 agent_host_->AttachClient(this); |
89 } | 333 } |
90 | 334 |
91 ~DevToolsAgentHostClientImpl() override { | 335 ~DevToolsAgentHostClientImpl() override { |
92 if (agent_host_.get()) | 336 if (agent_host_.get()) |
93 agent_host_->DetachClient(); | 337 agent_host_->DetachClient(); |
94 } | 338 } |
95 | 339 |
96 void AgentHostClosed(DevToolsAgentHost* agent_host, | 340 void AgentHostClosed(DevToolsAgentHost* agent_host, |
97 bool replaced_with_another_client) override { | 341 bool replaced_with_another_client) override { |
98 DCHECK(agent_host == agent_host_.get()); | 342 DCHECK(agent_host == agent_host_.get()); |
99 agent_host_ = NULL; | 343 agent_host_ = NULL; |
100 | 344 |
101 base::DictionaryValue notification; | 345 base::DictionaryValue notification; |
102 notification.SetString( | 346 notification.SetString( |
103 devtools::Inspector::detached::kParamReason, | 347 devtools::Inspector::detached::kParamReason, |
104 replaced_with_another_client ? | 348 replaced_with_another_client ? |
105 "replaced_with_devtools" : "target_closed"); | 349 "replaced_with_devtools" : "target_closed"); |
106 std::string response = DevToolsProtocol::CreateNotification( | 350 std::string response = DevToolsProtocol::CreateNotification( |
107 devtools::Inspector::detached::kName, | 351 devtools::Inspector::detached::kName, |
108 notification.DeepCopy())->Serialize(); | 352 notification.DeepCopy())->Serialize(); |
109 message_loop_->PostTask( | 353 message_loop_->PostTask( |
110 FROM_HERE, | 354 FROM_HERE, |
111 base::Bind(&net::HttpServer::SendOverWebSocket, | 355 base::Bind(&ServerWrapper::SendOverWebSocket, |
112 base::Unretained(server_), | 356 base::Unretained(server_wrapper_), |
113 connection_id_, | 357 connection_id_, |
114 response)); | 358 response)); |
115 | 359 |
116 message_loop_->PostTask( | 360 message_loop_->PostTask( |
117 FROM_HERE, | 361 FROM_HERE, |
118 base::Bind(&net::HttpServer::Close, | 362 base::Bind(&ServerWrapper::Close, |
119 base::Unretained(server_), | 363 base::Unretained(server_wrapper_), |
120 connection_id_)); | 364 connection_id_)); |
121 } | 365 } |
122 | 366 |
123 void DispatchProtocolMessage(DevToolsAgentHost* agent_host, | 367 void DispatchProtocolMessage(DevToolsAgentHost* agent_host, |
124 const std::string& message) override { | 368 const std::string& message) override { |
125 DCHECK(agent_host == agent_host_.get()); | 369 DCHECK(agent_host == agent_host_.get()); |
126 message_loop_->PostTask( | 370 message_loop_->PostTask( |
127 FROM_HERE, | 371 FROM_HERE, |
128 base::Bind(&net::HttpServer::SendOverWebSocket, | 372 base::Bind(&ServerWrapper::SendOverWebSocket, |
129 base::Unretained(server_), | 373 base::Unretained(server_wrapper_), |
130 connection_id_, | 374 connection_id_, |
131 message)); | 375 message)); |
132 } | 376 } |
133 | 377 |
134 void OnMessage(const std::string& message) { | 378 void OnMessage(const std::string& message) { |
135 if (agent_host_.get()) | 379 if (agent_host_.get()) |
136 agent_host_->DispatchProtocolMessage(message); | 380 agent_host_->DispatchProtocolMessage(message); |
137 } | 381 } |
138 | 382 |
139 private: | 383 private: |
140 base::MessageLoop* const message_loop_; | 384 base::MessageLoop* const message_loop_; |
141 net::HttpServer* const server_; | 385 ServerWrapper* const server_wrapper_; |
142 const int connection_id_; | 386 const int connection_id_; |
143 scoped_refptr<DevToolsAgentHost> agent_host_; | 387 scoped_refptr<DevToolsAgentHost> agent_host_; |
144 }; | 388 }; |
145 | 389 |
146 static bool TimeComparator(const DevToolsTarget* target1, | 390 static bool TimeComparator(const DevToolsTarget* target1, |
147 const DevToolsTarget* target2) { | 391 const DevToolsTarget* target2) { |
148 return target1->GetLastActivityTime() > target2->GetLastActivityTime(); | 392 return target1->GetLastActivityTime() > target2->GetLastActivityTime(); |
149 } | 393 } |
150 | 394 |
151 } // namespace | 395 // BrowserTarget ------------------------------------------------------------- |
152 | 396 |
153 // DevToolsHttpHandlerImpl::BrowserTarget ------------------------------------ | 397 class BrowserTarget { |
154 | |
155 class DevToolsHttpHandlerImpl::BrowserTarget { | |
156 public: | 398 public: |
157 BrowserTarget(base::MessageLoop* message_loop, | 399 BrowserTarget(base::MessageLoop* message_loop, |
158 net::HttpServer* server, | 400 ServerWrapper* server_wrapper, |
159 int connection_id) | 401 int connection_id) |
160 : message_loop_(message_loop), | 402 : message_loop_(message_loop), |
161 server_(server), | 403 server_wrapper_(server_wrapper), |
162 connection_id_(connection_id), | 404 connection_id_(connection_id), |
163 tracing_handler_(new devtools::tracing::TracingHandler( | 405 tracing_handler_(new devtools::tracing::TracingHandler( |
164 devtools::tracing::TracingHandler::Browser)), | 406 devtools::tracing::TracingHandler::Browser)), |
165 protocol_handler_(new DevToolsProtocolHandlerImpl()) { | 407 protocol_handler_(new DevToolsProtocolHandlerImpl()) { |
166 protocol_handler_->SetNotifier( | 408 protocol_handler_->SetNotifier( |
167 base::Bind(&BrowserTarget::Respond, base::Unretained(this))); | 409 base::Bind(&BrowserTarget::Respond, base::Unretained(this))); |
168 protocol_handler_->SetTracingHandler(tracing_handler_.get()); | 410 protocol_handler_->SetTracingHandler(tracing_handler_.get()); |
169 } | 411 } |
170 | 412 |
171 ~BrowserTarget() { | 413 ~BrowserTarget() { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
203 Respond(response->Serialize()); | 445 Respond(response->Serialize()); |
204 } else { | 446 } else { |
205 Respond(command->NoSuchMethodErrorResponse()->Serialize()); | 447 Respond(command->NoSuchMethodErrorResponse()->Serialize()); |
206 } | 448 } |
207 } | 449 } |
208 | 450 |
209 void Respond(const std::string& message) { | 451 void Respond(const std::string& message) { |
210 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 452 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
211 message_loop_->PostTask( | 453 message_loop_->PostTask( |
212 FROM_HERE, | 454 FROM_HERE, |
213 base::Bind(&net::HttpServer::SendOverWebSocket, | 455 base::Bind(&ServerWrapper::SendOverWebSocket, |
214 base::Unretained(server_), | 456 base::Unretained(server_wrapper_), |
215 connection_id_, | 457 connection_id_, |
216 message)); | 458 message)); |
217 } | 459 } |
218 | 460 |
219 private: | 461 private: |
220 base::MessageLoop* const message_loop_; | 462 base::MessageLoop* const message_loop_; |
221 net::HttpServer* const server_; | 463 ServerWrapper* const server_wrapper_; |
222 const int connection_id_; | 464 const int connection_id_; |
223 scoped_ptr<devtools::tracing::TracingHandler> tracing_handler_; | 465 scoped_ptr<devtools::tracing::TracingHandler> tracing_handler_; |
224 scoped_ptr<DevToolsProtocolHandlerImpl> protocol_handler_; | 466 scoped_ptr<DevToolsProtocolHandlerImpl> protocol_handler_; |
225 std::vector<DevToolsProtocol::Handler*> handlers_; | 467 std::vector<DevToolsProtocol::Handler*> handlers_; |
226 }; | 468 }; |
227 | 469 |
470 } // namespace | |
471 | |
228 // DevToolsHttpHandler ------------------------------------------------------- | 472 // DevToolsHttpHandler ------------------------------------------------------- |
229 | 473 |
230 // static | 474 // static |
231 bool DevToolsHttpHandler::IsSupportedProtocolVersion( | 475 bool DevToolsHttpHandler::IsSupportedProtocolVersion( |
232 const std::string& version) { | 476 const std::string& version) { |
233 return devtools::IsSupportedProtocolVersion(version); | 477 return devtools::IsSupportedProtocolVersion(version); |
234 } | 478 } |
235 | 479 |
236 // static | 480 // static |
237 int DevToolsHttpHandler::GetFrontendResourceId(const std::string& name) { | 481 int DevToolsHttpHandler::GetFrontendResourceId(const std::string& name) { |
238 for (size_t i = 0; i < kDevtoolsResourcesSize; ++i) { | 482 for (size_t i = 0; i < kDevtoolsResourcesSize; ++i) { |
239 if (name == kDevtoolsResources[i].name) | 483 if (name == kDevtoolsResources[i].name) |
240 return kDevtoolsResources[i].value; | 484 return kDevtoolsResources[i].value; |
241 } | 485 } |
242 return -1; | 486 return -1; |
243 } | 487 } |
244 | 488 |
245 // static | 489 // static |
246 DevToolsHttpHandler* DevToolsHttpHandler::Start( | 490 DevToolsHttpHandler* DevToolsHttpHandler::Start( |
247 scoped_ptr<ServerSocketFactory> server_socket_factory, | 491 scoped_ptr<ServerSocketFactory> server_socket_factory, |
248 const std::string& frontend_url, | 492 const std::string& frontend_url, |
249 DevToolsHttpHandlerDelegate* delegate, | 493 DevToolsHttpHandlerDelegate* delegate, |
250 const base::FilePath& active_port_output_directory) { | 494 const base::FilePath& active_port_output_directory) { |
251 DevToolsHttpHandlerImpl* http_handler = | 495 DevToolsHttpHandlerImpl* http_handler = |
252 new DevToolsHttpHandlerImpl(server_socket_factory.Pass(), | 496 new DevToolsHttpHandlerImpl(server_socket_factory.Pass(), |
253 frontend_url, | 497 frontend_url, |
254 delegate, | 498 delegate, |
255 active_port_output_directory); | 499 active_port_output_directory); |
256 http_handler->Start(); | |
257 return http_handler; | 500 return http_handler; |
258 } | 501 } |
259 | 502 |
260 // DevToolsHttpHandler::ServerSocketFactory ---------------------------------- | 503 // DevToolsHttpHandler::ServerSocketFactory ---------------------------------- |
261 | 504 |
262 DevToolsHttpHandler::ServerSocketFactory::ServerSocketFactory( | 505 DevToolsHttpHandler::ServerSocketFactory::ServerSocketFactory( |
263 const std::string& address, | 506 const std::string& address, |
264 int port, | 507 int port, |
265 int backlog) | 508 int backlog) |
266 : address_(address), | 509 : address_(address), |
(...skipping 10 matching lines...) Expand all Loading... | |
277 if (socket && | 520 if (socket && |
278 socket->ListenWithAddressAndPort(address_, port_, backlog_) == net::OK) { | 521 socket->ListenWithAddressAndPort(address_, port_, backlog_) == net::OK) { |
279 return socket.Pass(); | 522 return socket.Pass(); |
280 } | 523 } |
281 return scoped_ptr<net::ServerSocket>(); | 524 return scoped_ptr<net::ServerSocket>(); |
282 } | 525 } |
283 | 526 |
284 // DevToolsHttpHandlerImpl --------------------------------------------------- | 527 // DevToolsHttpHandlerImpl --------------------------------------------------- |
285 | 528 |
286 DevToolsHttpHandlerImpl::~DevToolsHttpHandlerImpl() { | 529 DevToolsHttpHandlerImpl::~DevToolsHttpHandlerImpl() { |
287 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
288 // Stop() must be called prior to destruction. | |
289 DCHECK(server_.get() == NULL); | |
290 DCHECK(thread_.get() == NULL); | |
291 STLDeleteValues(&target_map_); | 530 STLDeleteValues(&target_map_); |
292 } | 531 STLDeleteValues(&browser_targets_); |
293 | 532 STLDeleteValues(&connection_to_client_); |
294 void DevToolsHttpHandlerImpl::Start() { | |
295 if (thread_) | |
296 return; | |
297 thread_.reset(new base::Thread(kDevToolsHandlerThreadName)); | |
298 BrowserThread::PostTask( | |
299 BrowserThread::FILE, FROM_HERE, | |
300 base::Bind(&DevToolsHttpHandlerImpl::StartHandlerThread, this)); | |
301 } | |
302 | |
303 // Runs on FILE thread. | |
304 void DevToolsHttpHandlerImpl::StartHandlerThread() { | |
305 base::Thread::Options options; | |
306 options.message_loop_type = base::MessageLoop::TYPE_IO; | |
307 if (!thread_->StartWithOptions(options)) { | |
308 BrowserThread::PostTask( | |
309 BrowserThread::UI, FROM_HERE, | |
310 base::Bind(&DevToolsHttpHandlerImpl::ResetHandlerThread, this)); | |
311 return; | |
312 } | |
313 | |
314 thread_->message_loop()->PostTask( | |
315 FROM_HERE, | |
316 base::Bind(&DevToolsHttpHandlerImpl::Init, this)); | |
317 } | |
318 | |
319 void DevToolsHttpHandlerImpl::ResetHandlerThread() { | |
320 thread_.reset(); | |
321 server_ip_address_.reset(); | |
322 } | |
323 | |
324 void DevToolsHttpHandlerImpl::ResetHandlerThreadAndRelease() { | |
325 ResetHandlerThread(); | |
326 Release(); | |
327 } | 533 } |
328 | 534 |
329 void DevToolsHttpHandlerImpl::Stop() { | 535 void DevToolsHttpHandlerImpl::Stop() { |
330 if (!thread_) | 536 Terminate(thread_, server_wrapper_); |
331 return; | 537 delete this; |
332 BrowserThread::PostTaskAndReply( | |
333 BrowserThread::FILE, FROM_HERE, | |
334 base::Bind(&DevToolsHttpHandlerImpl::StopHandlerThread, this), | |
335 base::Bind(&DevToolsHttpHandlerImpl::ResetHandlerThreadAndRelease, this)); | |
336 } | |
337 | |
338 void DevToolsHttpHandlerImpl::StopWithoutRelease() { | |
339 if (!thread_) | |
340 return; | |
341 BrowserThread::PostTaskAndReply( | |
342 BrowserThread::FILE, FROM_HERE, | |
343 base::Bind(&DevToolsHttpHandlerImpl::StopHandlerThread, this), | |
344 base::Bind(&DevToolsHttpHandlerImpl::ResetHandlerThread, this)); | |
345 } | 538 } |
346 | 539 |
347 GURL DevToolsHttpHandlerImpl::GetFrontendURL() { | 540 GURL DevToolsHttpHandlerImpl::GetFrontendURL() { |
348 if (!server_ip_address_) | 541 if (!server_ip_address_) |
349 return GURL(); | 542 return GURL(); |
350 return GURL(std::string("http://") + server_ip_address_->ToString() + frontend _url_); | 543 return GURL(std::string("http://") + server_ip_address_->ToString() + frontend _url_); |
351 } | 544 } |
352 | 545 |
353 static std::string PathWithoutParams(const std::string& path) { | 546 static std::string PathWithoutParams(const std::string& path) { |
354 size_t query_position = path.find("?"); | 547 size_t query_position = path.find("?"); |
(...skipping 16 matching lines...) Expand all Loading... | |
371 } else if (EndsWith(filename, ".json", false)) { | 564 } else if (EndsWith(filename, ".json", false)) { |
372 return "application/json"; | 565 return "application/json"; |
373 } | 566 } |
374 LOG(ERROR) << "GetMimeType doesn't know mime type for: " | 567 LOG(ERROR) << "GetMimeType doesn't know mime type for: " |
375 << filename | 568 << filename |
376 << " text/plain will be returned"; | 569 << " text/plain will be returned"; |
377 NOTREACHED(); | 570 NOTREACHED(); |
378 return "text/plain"; | 571 return "text/plain"; |
379 } | 572 } |
380 | 573 |
381 void DevToolsHttpHandlerImpl::OnHttpRequest( | 574 void ServerWrapper::OnHttpRequest(int connection_id, |
382 int connection_id, | 575 const net::HttpServerRequestInfo& info) { |
383 const net::HttpServerRequestInfo& info) { | |
384 server_->SetSendBufferSize(connection_id, kSendBufferSizeForDevTools); | 576 server_->SetSendBufferSize(connection_id, kSendBufferSizeForDevTools); |
385 | 577 |
386 if (info.path.find("/json") == 0) { | 578 if (info.path.find("/json") == 0) { |
387 BrowserThread::PostTask( | 579 BrowserThread::PostTask( |
388 BrowserThread::UI, | 580 BrowserThread::UI, |
389 FROM_HERE, | 581 FROM_HERE, |
390 base::Bind(&DevToolsHttpHandlerImpl::OnJsonRequestUI, | 582 base::Bind(&DevToolsHttpHandlerImpl::OnJsonRequest, |
391 this, | 583 handler_, |
392 connection_id, | 584 connection_id, |
393 info)); | 585 info)); |
394 return; | 586 return; |
395 } | 587 } |
396 | 588 |
397 if (info.path.find(kThumbUrlPrefix) == 0) { | 589 if (info.path.find(kThumbUrlPrefix) == 0) { |
398 // Thumbnail request. | 590 // Thumbnail request. |
399 const std::string target_id = info.path.substr(strlen(kThumbUrlPrefix)); | 591 const std::string target_id = info.path.substr(strlen(kThumbUrlPrefix)); |
400 DevToolsTarget* target = GetTarget(target_id); | |
401 GURL page_url; | |
402 if (target) | |
403 page_url = target->GetURL(); | |
404 BrowserThread::PostTask( | 592 BrowserThread::PostTask( |
405 BrowserThread::UI, | 593 BrowserThread::UI, |
406 FROM_HERE, | 594 FROM_HERE, |
407 base::Bind(&DevToolsHttpHandlerImpl::OnThumbnailRequestUI, | 595 base::Bind(&DevToolsHttpHandlerImpl::OnThumbnailRequest, |
408 this, | 596 handler_, |
409 connection_id, | 597 connection_id, |
410 page_url)); | 598 target_id)); |
411 return; | 599 return; |
412 } | 600 } |
413 | 601 |
414 if (info.path == "" || info.path == "/") { | 602 if (info.path == "" || info.path == "/") { |
415 // Discovery page request. | 603 // Discovery page request. |
416 BrowserThread::PostTask( | 604 BrowserThread::PostTask( |
417 BrowserThread::UI, | 605 BrowserThread::UI, |
418 FROM_HERE, | 606 FROM_HERE, |
419 base::Bind(&DevToolsHttpHandlerImpl::OnDiscoveryPageRequestUI, | 607 base::Bind(&DevToolsHttpHandlerImpl::OnDiscoveryPageRequest, |
420 this, | 608 handler_, |
421 connection_id)); | 609 connection_id)); |
422 return; | 610 return; |
423 } | 611 } |
424 | 612 |
425 if (info.path.find("/devtools/") != 0) { | 613 if (info.path.find("/devtools/") != 0) { |
426 server_->Send404(connection_id); | 614 server_->Send404(connection_id); |
427 return; | 615 return; |
428 } | 616 } |
429 | 617 |
430 std::string filename = PathWithoutParams(info.path.substr(10)); | 618 std::string filename = PathWithoutParams(info.path.substr(10)); |
431 std::string mime_type = GetMimeType(filename); | 619 std::string mime_type = GetMimeType(filename); |
432 | 620 |
433 base::FilePath frontend_dir = delegate_->GetDebugFrontendDir(); | 621 if (!frontend_dir_.empty()) { |
434 if (!frontend_dir.empty()) { | 622 base::FilePath path = frontend_dir_.AppendASCII(filename); |
435 base::FilePath path = frontend_dir.AppendASCII(filename); | |
436 std::string data; | 623 std::string data; |
437 base::ReadFileToString(path, &data); | 624 base::ReadFileToString(path, &data); |
438 server_->Send200(connection_id, data, mime_type); | 625 server_->Send200(connection_id, data, mime_type); |
439 return; | 626 return; |
440 } | 627 } |
441 if (delegate_->BundlesFrontendResources()) { | 628 if (bundles_resources_) { |
442 int resource_id = DevToolsHttpHandler::GetFrontendResourceId(filename); | 629 int resource_id = DevToolsHttpHandler::GetFrontendResourceId(filename); |
443 if (resource_id != -1) { | 630 if (resource_id != -1) { |
444 base::StringPiece data = GetContentClient()->GetDataResource( | 631 base::StringPiece data = GetContentClient()->GetDataResource( |
445 resource_id, ui::SCALE_FACTOR_NONE); | 632 resource_id, ui::SCALE_FACTOR_NONE); |
446 server_->Send200(connection_id, data.as_string(), mime_type); | 633 server_->Send200(connection_id, data.as_string(), mime_type); |
447 return; | 634 return; |
448 } | 635 } |
449 } | 636 } |
450 server_->Send404(connection_id); | 637 server_->Send404(connection_id); |
451 } | 638 } |
452 | 639 |
453 void DevToolsHttpHandlerImpl::OnWebSocketRequest( | 640 void ServerWrapper::OnWebSocketRequest( |
454 int connection_id, | 641 int connection_id, |
455 const net::HttpServerRequestInfo& request) { | 642 const net::HttpServerRequestInfo& request) { |
456 BrowserThread::PostTask( | 643 BrowserThread::PostTask( |
457 BrowserThread::UI, | 644 BrowserThread::UI, |
458 FROM_HERE, | 645 FROM_HERE, |
459 base::Bind( | 646 base::Bind( |
460 &DevToolsHttpHandlerImpl::OnWebSocketRequestUI, | 647 &DevToolsHttpHandlerImpl::OnWebSocketRequest, |
461 this, | 648 handler_, |
462 connection_id, | 649 connection_id, |
463 request)); | 650 request)); |
464 } | 651 } |
465 | 652 |
466 void DevToolsHttpHandlerImpl::OnWebSocketMessage( | 653 void ServerWrapper::OnWebSocketMessage(int connection_id, |
467 int connection_id, | 654 const std::string& data) { |
468 const std::string& data) { | |
469 BrowserThread::PostTask( | 655 BrowserThread::PostTask( |
470 BrowserThread::UI, | 656 BrowserThread::UI, |
471 FROM_HERE, | 657 FROM_HERE, |
472 base::Bind( | 658 base::Bind( |
473 &DevToolsHttpHandlerImpl::OnWebSocketMessageUI, | 659 &DevToolsHttpHandlerImpl::OnWebSocketMessage, |
474 this, | 660 handler_, |
475 connection_id, | 661 connection_id, |
476 data)); | 662 data)); |
477 } | 663 } |
478 | 664 |
479 void DevToolsHttpHandlerImpl::OnClose(int connection_id) { | 665 void ServerWrapper::OnClose(int connection_id) { |
480 BrowserThread::PostTask( | 666 BrowserThread::PostTask( |
481 BrowserThread::UI, | 667 BrowserThread::UI, |
482 FROM_HERE, | 668 FROM_HERE, |
483 base::Bind( | 669 base::Bind( |
484 &DevToolsHttpHandlerImpl::OnCloseUI, | 670 &DevToolsHttpHandlerImpl::OnClose, |
485 this, | 671 handler_, |
486 connection_id)); | 672 connection_id)); |
487 } | 673 } |
488 | 674 |
489 std::string DevToolsHttpHandlerImpl::GetFrontendURLInternal( | 675 std::string DevToolsHttpHandlerImpl::GetFrontendURLInternal( |
490 const std::string id, | 676 const std::string id, |
491 const std::string& host) { | 677 const std::string& host) { |
492 return base::StringPrintf( | 678 return base::StringPrintf( |
493 "%s%sws=%s%s%s", | 679 "%s%sws=%s%s%s", |
494 frontend_url_.c_str(), | 680 frontend_url_.c_str(), |
495 frontend_url_.find("?") == std::string::npos ? "?" : "&", | 681 frontend_url_.find("?") == std::string::npos ? "?" : "&", |
(...skipping 20 matching lines...) Expand all Loading... | |
516 *command = path.substr(1); | 702 *command = path.substr(1); |
517 | 703 |
518 size_t separator_pos = command->find("/"); | 704 size_t separator_pos = command->find("/"); |
519 if (separator_pos != std::string::npos) { | 705 if (separator_pos != std::string::npos) { |
520 *target_id = command->substr(separator_pos + 1); | 706 *target_id = command->substr(separator_pos + 1); |
521 *command = command->substr(0, separator_pos); | 707 *command = command->substr(0, separator_pos); |
522 } | 708 } |
523 return true; | 709 return true; |
524 } | 710 } |
525 | 711 |
526 void DevToolsHttpHandlerImpl::OnJsonRequestUI( | 712 static void OnTargetListReceivedWeak( |
dgozman
2014/11/10 15:39:19
nit: I think this should be a static method on a c
vkuzkokov
2014/11/11 08:52:05
Done.
| |
713 base::WeakPtr<DevToolsHttpHandlerImpl> handler, | |
714 int connection_id, | |
715 const std::string& host, | |
716 const DevToolsManagerDelegate::TargetList& targets) { | |
717 if (handler) { | |
718 handler->OnTargetListReceived(connection_id, host, targets); | |
719 } else { | |
720 STLDeleteContainerPointers(targets.begin(), targets.end()); | |
721 } | |
722 } | |
723 | |
724 void DevToolsHttpHandlerImpl::OnJsonRequest( | |
527 int connection_id, | 725 int connection_id, |
528 const net::HttpServerRequestInfo& info) { | 726 const net::HttpServerRequestInfo& info) { |
529 // Trim /json | 727 // Trim /json |
530 std::string path = info.path.substr(5); | 728 std::string path = info.path.substr(5); |
531 | 729 |
532 // Trim fragment and query | 730 // Trim fragment and query |
533 std::string query; | 731 std::string query; |
534 size_t query_pos = path.find("?"); | 732 size_t query_pos = path.find("?"); |
535 if (query_pos != std::string::npos) { | 733 if (query_pos != std::string::npos) { |
536 query = path.substr(query_pos + 1); | 734 query = path.substr(query_pos + 1); |
(...skipping 23 matching lines...) Expand all Loading... | |
560 #if defined(OS_ANDROID) | 758 #if defined(OS_ANDROID) |
561 version.SetString("Android-Package", | 759 version.SetString("Android-Package", |
562 base::android::BuildInfo::GetInstance()->package_name()); | 760 base::android::BuildInfo::GetInstance()->package_name()); |
563 #endif | 761 #endif |
564 SendJson(connection_id, net::HTTP_OK, &version, std::string()); | 762 SendJson(connection_id, net::HTTP_OK, &version, std::string()); |
565 return; | 763 return; |
566 } | 764 } |
567 | 765 |
568 if (command == "list") { | 766 if (command == "list") { |
569 std::string host = info.headers["host"]; | 767 std::string host = info.headers["host"]; |
570 AddRef(); // Balanced in OnTargetListReceived. | |
571 DevToolsManagerDelegate* manager_delegate = | 768 DevToolsManagerDelegate* manager_delegate = |
572 DevToolsManager::GetInstance()->delegate(); | 769 DevToolsManager::GetInstance()->delegate(); |
573 if (manager_delegate) { | 770 if (manager_delegate) { |
574 manager_delegate->EnumerateTargets( | 771 manager_delegate->EnumerateTargets( |
575 base::Bind(&DevToolsHttpHandlerImpl::OnTargetListReceived, | 772 base::Bind(&OnTargetListReceivedWeak, |
576 this, connection_id, host)); | 773 weak_factory_.GetWeakPtr(), connection_id, host)); |
577 } else { | 774 } else { |
578 DevToolsManagerDelegate::TargetList empty_list; | 775 DevToolsManagerDelegate::TargetList empty_list; |
579 OnTargetListReceived(connection_id, host, empty_list); | 776 OnTargetListReceived(connection_id, host, empty_list); |
580 } | 777 } |
581 return; | 778 return; |
582 } | 779 } |
583 | 780 |
584 if (command == "new") { | 781 if (command == "new") { |
585 GURL url(net::UnescapeURLComponent( | 782 GURL url(net::UnescapeURLComponent( |
586 query, net::UnescapeRule::URL_SPECIAL_CHARS)); | 783 query, net::UnescapeRule::URL_SPECIAL_CHARS)); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
657 | 854 |
658 STLDeleteValues(&target_map_); | 855 STLDeleteValues(&target_map_); |
659 base::ListValue list_value; | 856 base::ListValue list_value; |
660 for (DevToolsManagerDelegate::TargetList::const_iterator it = | 857 for (DevToolsManagerDelegate::TargetList::const_iterator it = |
661 sorted_targets.begin(); it != sorted_targets.end(); ++it) { | 858 sorted_targets.begin(); it != sorted_targets.end(); ++it) { |
662 DevToolsTarget* target = *it; | 859 DevToolsTarget* target = *it; |
663 target_map_[target->GetId()] = target; | 860 target_map_[target->GetId()] = target; |
664 list_value.Append(SerializeTarget(*target, host)); | 861 list_value.Append(SerializeTarget(*target, host)); |
665 } | 862 } |
666 SendJson(connection_id, net::HTTP_OK, &list_value, std::string()); | 863 SendJson(connection_id, net::HTTP_OK, &list_value, std::string()); |
667 Release(); // Balanced in OnJsonRequestUI. | |
668 } | 864 } |
669 | 865 |
670 DevToolsTarget* DevToolsHttpHandlerImpl::GetTarget(const std::string& id) { | 866 DevToolsTarget* DevToolsHttpHandlerImpl::GetTarget(const std::string& id) { |
671 TargetMap::const_iterator it = target_map_.find(id); | 867 TargetMap::const_iterator it = target_map_.find(id); |
672 if (it == target_map_.end()) | 868 if (it == target_map_.end()) |
673 return NULL; | 869 return NULL; |
674 return it->second; | 870 return it->second; |
675 } | 871 } |
676 | 872 |
677 void DevToolsHttpHandlerImpl::OnThumbnailRequestUI( | 873 void DevToolsHttpHandlerImpl::OnThumbnailRequest( |
678 int connection_id, const GURL& page_url) { | 874 int connection_id, const std::string& target_id) { |
875 DevToolsTarget* target = GetTarget(target_id); | |
876 GURL page_url; | |
877 if (target) | |
878 page_url = target->GetURL(); | |
679 DevToolsManagerDelegate* manager_delegate = | 879 DevToolsManagerDelegate* manager_delegate = |
680 DevToolsManager::GetInstance()->delegate(); | 880 DevToolsManager::GetInstance()->delegate(); |
681 std::string data = | 881 std::string data = |
682 manager_delegate ? manager_delegate->GetPageThumbnailData(page_url) : ""; | 882 manager_delegate ? manager_delegate->GetPageThumbnailData(page_url) : ""; |
683 if (!data.empty()) | 883 if (!data.empty()) |
684 Send200(connection_id, data, "image/png"); | 884 Send200(connection_id, data, "image/png"); |
685 else | 885 else |
686 Send404(connection_id); | 886 Send404(connection_id); |
687 } | 887 } |
688 | 888 |
689 void DevToolsHttpHandlerImpl::OnDiscoveryPageRequestUI(int connection_id) { | 889 void DevToolsHttpHandlerImpl::OnDiscoveryPageRequest(int connection_id) { |
690 std::string response = delegate_->GetDiscoveryPageHTML(); | 890 std::string response = delegate_->GetDiscoveryPageHTML(); |
691 Send200(connection_id, response, "text/html; charset=UTF-8"); | 891 Send200(connection_id, response, "text/html; charset=UTF-8"); |
692 } | 892 } |
693 | 893 |
694 void DevToolsHttpHandlerImpl::OnWebSocketRequestUI( | 894 void DevToolsHttpHandlerImpl::OnWebSocketRequest( |
695 int connection_id, | 895 int connection_id, |
696 const net::HttpServerRequestInfo& request) { | 896 const net::HttpServerRequestInfo& request) { |
697 if (!thread_) | 897 if (!thread_) |
698 return; | 898 return; |
699 | 899 |
700 std::string browser_prefix = "/devtools/browser"; | 900 std::string browser_prefix = "/devtools/browser"; |
701 size_t browser_pos = request.path.find(browser_prefix); | 901 size_t browser_pos = request.path.find(browser_prefix); |
702 if (browser_pos == 0) { | 902 if (browser_pos == 0) { |
703 BrowserTarget* browser_target = new BrowserTarget( | 903 BrowserTarget* browser_target = new BrowserTarget( |
704 thread_->message_loop(), server_.get(), connection_id); | 904 thread_->message_loop(), server_wrapper_, connection_id); |
705 browser_target->RegisterHandler( | 905 browser_target->RegisterHandler( |
706 new TetheringHandler(delegate_.get(), thread_->message_loop_proxy())); | 906 new TetheringHandler(delegate_.get(), thread_->message_loop_proxy())); |
707 browser_target->RegisterHandler( | 907 browser_target->RegisterHandler( |
708 new DevToolsSystemInfoHandler()); | 908 new DevToolsSystemInfoHandler()); |
709 browser_targets_[connection_id] = browser_target; | 909 browser_targets_[connection_id] = browser_target; |
710 AcceptWebSocket(connection_id, request); | 910 AcceptWebSocket(connection_id, request); |
711 return; | 911 return; |
712 } | 912 } |
713 | 913 |
714 size_t pos = request.path.find(kPageUrlPrefix); | 914 size_t pos = request.path.find(kPageUrlPrefix); |
(...skipping 11 matching lines...) Expand all Loading... | |
726 return; | 926 return; |
727 } | 927 } |
728 | 928 |
729 if (agent->IsAttached()) { | 929 if (agent->IsAttached()) { |
730 Send500(connection_id, | 930 Send500(connection_id, |
731 "Target with given id is being inspected: " + page_id); | 931 "Target with given id is being inspected: " + page_id); |
732 return; | 932 return; |
733 } | 933 } |
734 | 934 |
735 DevToolsAgentHostClientImpl* client_host = new DevToolsAgentHostClientImpl( | 935 DevToolsAgentHostClientImpl* client_host = new DevToolsAgentHostClientImpl( |
736 thread_->message_loop(), server_.get(), connection_id, agent.get()); | 936 thread_->message_loop(), server_wrapper_, connection_id, agent.get()); |
737 connection_to_client_ui_[connection_id] = client_host; | 937 connection_to_client_[connection_id] = client_host; |
738 | 938 |
739 AcceptWebSocket(connection_id, request); | 939 AcceptWebSocket(connection_id, request); |
740 } | 940 } |
741 | 941 |
742 void DevToolsHttpHandlerImpl::OnWebSocketMessageUI( | 942 void DevToolsHttpHandlerImpl::OnWebSocketMessage( |
743 int connection_id, | 943 int connection_id, |
744 const std::string& data) { | 944 const std::string& data) { |
745 BrowserTargets::iterator browser_it = browser_targets_.find(connection_id); | 945 BrowserTargets::iterator browser_it = browser_targets_.find(connection_id); |
746 if (browser_it != browser_targets_.end()) { | 946 if (browser_it != browser_targets_.end()) { |
747 browser_it->second->HandleMessage(data); | 947 browser_it->second->HandleMessage(data); |
748 return; | 948 return; |
749 } | 949 } |
750 | 950 |
751 ConnectionToClientMap::iterator it = | 951 ConnectionToClientMap::iterator it = |
752 connection_to_client_ui_.find(connection_id); | 952 connection_to_client_.find(connection_id); |
753 if (it == connection_to_client_ui_.end()) | 953 if (it != connection_to_client_.end()) |
754 return; | 954 it->second->OnMessage(data); |
755 | |
756 DevToolsAgentHostClientImpl* client = | |
757 static_cast<DevToolsAgentHostClientImpl*>(it->second); | |
758 client->OnMessage(data); | |
759 } | 955 } |
760 | 956 |
761 void DevToolsHttpHandlerImpl::OnCloseUI(int connection_id) { | 957 void DevToolsHttpHandlerImpl::OnClose(int connection_id) { |
762 BrowserTargets::iterator browser_it = browser_targets_.find(connection_id); | 958 BrowserTargets::iterator browser_it = browser_targets_.find(connection_id); |
763 if (browser_it != browser_targets_.end()) { | 959 if (browser_it != browser_targets_.end()) { |
764 delete browser_it->second; | 960 delete browser_it->second; |
765 browser_targets_.erase(connection_id); | 961 browser_targets_.erase(connection_id); |
766 return; | 962 return; |
767 } | 963 } |
768 | 964 |
769 ConnectionToClientMap::iterator it = | 965 ConnectionToClientMap::iterator it = |
770 connection_to_client_ui_.find(connection_id); | 966 connection_to_client_.find(connection_id); |
771 if (it != connection_to_client_ui_.end()) { | 967 if (it != connection_to_client_.end()) { |
772 DevToolsAgentHostClientImpl* client = | 968 delete it->second; |
773 static_cast<DevToolsAgentHostClientImpl*>(it->second); | 969 connection_to_client_.erase(connection_id); |
774 delete client; | |
775 connection_to_client_ui_.erase(connection_id); | |
776 } | 970 } |
777 } | 971 } |
778 | 972 |
779 void DevToolsHttpHandlerImpl::OnHttpServerInitialized( | |
780 const net::IPEndPoint& ip_address) { | |
781 server_ip_address_.reset(new net::IPEndPoint(ip_address)); | |
782 } | |
783 | |
784 DevToolsHttpHandlerImpl::DevToolsHttpHandlerImpl( | 973 DevToolsHttpHandlerImpl::DevToolsHttpHandlerImpl( |
785 scoped_ptr<ServerSocketFactory> server_socket_factory, | 974 scoped_ptr<ServerSocketFactory> server_socket_factory, |
786 const std::string& frontend_url, | 975 const std::string& frontend_url, |
787 DevToolsHttpHandlerDelegate* delegate, | 976 DevToolsHttpHandlerDelegate* delegate, |
788 const base::FilePath& active_port_output_directory) | 977 const base::FilePath& output_directory) |
789 : frontend_url_(frontend_url), | 978 : thread_(nullptr), |
790 server_socket_factory_(server_socket_factory.Pass()), | 979 frontend_url_(frontend_url), |
980 server_wrapper_(nullptr), | |
791 delegate_(delegate), | 981 delegate_(delegate), |
792 active_port_output_directory_(active_port_output_directory) { | 982 weak_factory_(this) { |
793 if (frontend_url_.empty()) | 983 if (frontend_url_.empty()) |
794 frontend_url_ = "/devtools/devtools.html"; | 984 frontend_url_ = "/devtools/devtools.html"; |
795 | 985 |
796 // Balanced in ResetHandlerThreadAndRelease(). | 986 BrowserThread::PostTask( |
797 AddRef(); | 987 BrowserThread::FILE, FROM_HERE, |
988 base::Bind(&StartServerOnFile, | |
989 weak_factory_.GetWeakPtr(), | |
990 base::Passed(&server_socket_factory), | |
991 output_directory, | |
992 delegate_->GetDebugFrontendDir(), | |
993 delegate_->BundlesFrontendResources())); | |
798 } | 994 } |
799 | 995 |
800 // Runs on the handler thread | 996 void DevToolsHttpHandlerImpl::ServerStarted( |
801 void DevToolsHttpHandlerImpl::Init() { | 997 base::Thread* thread, |
802 scoped_ptr<net::ServerSocket> server_socket = | 998 ServerWrapper* server_wrapper, |
803 server_socket_factory_->CreateAndListen(); | 999 scoped_ptr<net::IPEndPoint> ip_address) { |
804 if (!server_socket) { | 1000 thread_ = thread; |
805 LOG(ERROR) << "Cannot start http server for devtools. Stop devtools."; | 1001 server_wrapper_ = server_wrapper; |
806 BrowserThread::PostTask( | 1002 server_ip_address_.swap(ip_address); |
807 BrowserThread::UI, FROM_HERE, | |
808 base::Bind(&DevToolsHttpHandlerImpl::StopWithoutRelease, this)); | |
809 return; | |
810 } | |
811 | |
812 server_.reset(new net::HttpServer(server_socket.Pass(), this)); | |
813 net::IPEndPoint ip_address; | |
814 server_->GetLocalAddress(&ip_address); | |
815 BrowserThread::PostTask( | |
816 BrowserThread::UI, FROM_HERE, | |
817 base::Bind(&DevToolsHttpHandlerImpl::OnHttpServerInitialized, | |
818 this, ip_address)); | |
819 if (!active_port_output_directory_.empty()) | |
820 WriteActivePortToUserProfile(); | |
821 } | 1003 } |
822 | 1004 |
823 // Runs on the handler thread | 1005 void ServerWrapper::WriteActivePortToUserProfile( |
824 void DevToolsHttpHandlerImpl::Teardown() { | 1006 const base::FilePath& output_directory) { |
825 server_.reset(); | 1007 DCHECK(!output_directory.empty()); |
826 } | |
827 | |
828 // Runs on FILE thread to make sure that it is serialized against | |
829 // {Start|Stop}HandlerThread and to allow calling pthread_join. | |
830 void DevToolsHttpHandlerImpl::StopHandlerThread() { | |
831 if (!thread_->message_loop()) | |
832 return; | |
833 thread_->message_loop()->PostTask( | |
834 FROM_HERE, | |
835 base::Bind(&DevToolsHttpHandlerImpl::Teardown, this)); | |
836 // Thread::Stop joins the thread. | |
837 thread_->Stop(); | |
838 } | |
839 | |
840 void DevToolsHttpHandlerImpl::WriteActivePortToUserProfile() { | |
841 DCHECK(!active_port_output_directory_.empty()); | |
842 net::IPEndPoint endpoint; | 1008 net::IPEndPoint endpoint; |
843 int err; | 1009 int err; |
844 if ((err = server_->GetLocalAddress(&endpoint)) != net::OK) { | 1010 if ((err = server_->GetLocalAddress(&endpoint)) != net::OK) { |
845 LOG(ERROR) << "Error " << err << " getting local address"; | 1011 LOG(ERROR) << "Error " << err << " getting local address"; |
846 return; | 1012 return; |
847 } | 1013 } |
848 | 1014 |
849 // Write this port to a well-known file in the profile directory | 1015 // Write this port to a well-known file in the profile directory |
850 // so Telemetry can pick it up. | 1016 // so Telemetry can pick it up. |
851 base::FilePath path = active_port_output_directory_.Append( | 1017 base::FilePath path = output_directory.Append(kDevToolsActivePortFileName); |
852 kDevToolsActivePortFileName); | |
853 std::string port_string = base::IntToString(endpoint.port()); | 1018 std::string port_string = base::IntToString(endpoint.port()); |
854 if (base::WriteFile(path, port_string.c_str(), port_string.length()) < 0) { | 1019 if (base::WriteFile(path, port_string.c_str(), port_string.length()) < 0) { |
855 LOG(ERROR) << "Error writing DevTools active port to file"; | 1020 LOG(ERROR) << "Error writing DevTools active port to file"; |
856 } | 1021 } |
857 } | 1022 } |
858 | 1023 |
859 void DevToolsHttpHandlerImpl::SendJson(int connection_id, | 1024 void DevToolsHttpHandlerImpl::SendJson(int connection_id, |
860 net::HttpStatusCode status_code, | 1025 net::HttpStatusCode status_code, |
861 base::Value* value, | 1026 base::Value* value, |
862 const std::string& message) { | 1027 const std::string& message) { |
863 if (!thread_) | 1028 if (!thread_) |
864 return; | 1029 return; |
865 | 1030 |
866 // Serialize value and message. | 1031 // Serialize value and message. |
867 std::string json_value; | 1032 std::string json_value; |
868 if (value) { | 1033 if (value) { |
869 base::JSONWriter::WriteWithOptions(value, | 1034 base::JSONWriter::WriteWithOptions(value, |
870 base::JSONWriter::OPTIONS_PRETTY_PRINT, | 1035 base::JSONWriter::OPTIONS_PRETTY_PRINT, |
871 &json_value); | 1036 &json_value); |
872 } | 1037 } |
873 std::string json_message; | 1038 std::string json_message; |
874 scoped_ptr<base::Value> message_object(new base::StringValue(message)); | 1039 scoped_ptr<base::Value> message_object(new base::StringValue(message)); |
875 base::JSONWriter::Write(message_object.get(), &json_message); | 1040 base::JSONWriter::Write(message_object.get(), &json_message); |
876 | 1041 |
877 net::HttpServerResponseInfo response(status_code); | 1042 net::HttpServerResponseInfo response(status_code); |
878 response.SetBody(json_value + message, "application/json; charset=UTF-8"); | 1043 response.SetBody(json_value + message, "application/json; charset=UTF-8"); |
879 | 1044 |
880 thread_->message_loop()->PostTask( | 1045 thread_->message_loop()->PostTask( |
881 FROM_HERE, | 1046 FROM_HERE, |
882 base::Bind(&net::HttpServer::SendResponse, | 1047 base::Bind(&ServerWrapper::SendResponse, |
883 base::Unretained(server_.get()), | 1048 base::Unretained(server_wrapper_), |
884 connection_id, | 1049 connection_id, |
885 response)); | 1050 response)); |
886 } | 1051 } |
887 | 1052 |
888 void DevToolsHttpHandlerImpl::Send200(int connection_id, | 1053 void DevToolsHttpHandlerImpl::Send200(int connection_id, |
889 const std::string& data, | 1054 const std::string& data, |
890 const std::string& mime_type) { | 1055 const std::string& mime_type) { |
891 if (!thread_) | 1056 if (!thread_) |
892 return; | 1057 return; |
893 thread_->message_loop()->PostTask( | 1058 thread_->message_loop()->PostTask( |
894 FROM_HERE, | 1059 FROM_HERE, |
895 base::Bind(&net::HttpServer::Send200, | 1060 base::Bind(&ServerWrapper::Send200, |
896 base::Unretained(server_.get()), | 1061 base::Unretained(server_wrapper_), |
897 connection_id, | 1062 connection_id, |
898 data, | 1063 data, |
899 mime_type)); | 1064 mime_type)); |
900 } | 1065 } |
901 | 1066 |
902 void DevToolsHttpHandlerImpl::Send404(int connection_id) { | 1067 void DevToolsHttpHandlerImpl::Send404(int connection_id) { |
903 if (!thread_) | 1068 if (!thread_) |
904 return; | 1069 return; |
905 thread_->message_loop()->PostTask( | 1070 thread_->message_loop()->PostTask( |
906 FROM_HERE, | 1071 FROM_HERE, |
907 base::Bind(&net::HttpServer::Send404, | 1072 base::Bind(&ServerWrapper::Send404, |
908 base::Unretained(server_.get()), | 1073 base::Unretained(server_wrapper_), |
909 connection_id)); | 1074 connection_id)); |
910 } | 1075 } |
911 | 1076 |
912 void DevToolsHttpHandlerImpl::Send500(int connection_id, | 1077 void DevToolsHttpHandlerImpl::Send500(int connection_id, |
913 const std::string& message) { | 1078 const std::string& message) { |
914 if (!thread_) | 1079 if (!thread_) |
915 return; | 1080 return; |
916 thread_->message_loop()->PostTask( | 1081 thread_->message_loop()->PostTask( |
917 FROM_HERE, | 1082 FROM_HERE, |
918 base::Bind(&net::HttpServer::Send500, | 1083 base::Bind(&ServerWrapper::Send500, |
919 base::Unretained(server_.get()), | 1084 base::Unretained(server_wrapper_), |
920 connection_id, | 1085 connection_id, |
921 message)); | 1086 message)); |
922 } | 1087 } |
923 | 1088 |
924 void DevToolsHttpHandlerImpl::AcceptWebSocket( | 1089 void DevToolsHttpHandlerImpl::AcceptWebSocket( |
925 int connection_id, | 1090 int connection_id, |
926 const net::HttpServerRequestInfo& request) { | 1091 const net::HttpServerRequestInfo& request) { |
927 if (!thread_) | 1092 if (!thread_) |
928 return; | 1093 return; |
929 thread_->message_loop()->PostTask( | 1094 thread_->message_loop()->PostTask( |
930 FROM_HERE, | 1095 FROM_HERE, |
931 base::Bind(&net::HttpServer::SetSendBufferSize, | 1096 base::Bind(&ServerWrapper::AcceptWebSocket, |
932 base::Unretained(server_.get()), | 1097 base::Unretained(server_wrapper_), |
933 connection_id, | |
934 kSendBufferSizeForDevTools)); | |
935 thread_->message_loop()->PostTask( | |
936 FROM_HERE, | |
937 base::Bind(&net::HttpServer::AcceptWebSocket, | |
938 base::Unretained(server_.get()), | |
939 connection_id, | 1098 connection_id, |
940 request)); | 1099 request)); |
941 } | 1100 } |
942 | 1101 |
943 base::DictionaryValue* DevToolsHttpHandlerImpl::SerializeTarget( | 1102 base::DictionaryValue* DevToolsHttpHandlerImpl::SerializeTarget( |
944 const DevToolsTarget& target, | 1103 const DevToolsTarget& target, |
945 const std::string& host) { | 1104 const std::string& host) { |
946 base::DictionaryValue* dictionary = new base::DictionaryValue; | 1105 base::DictionaryValue* dictionary = new base::DictionaryValue; |
947 | 1106 |
948 std::string id = target.GetId(); | 1107 std::string id = target.GetId(); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
980 id.c_str(), | 1139 id.c_str(), |
981 host); | 1140 host); |
982 dictionary->SetString( | 1141 dictionary->SetString( |
983 kTargetDevtoolsFrontendUrlField, devtools_frontend_url); | 1142 kTargetDevtoolsFrontendUrlField, devtools_frontend_url); |
984 } | 1143 } |
985 | 1144 |
986 return dictionary; | 1145 return dictionary; |
987 } | 1146 } |
988 | 1147 |
989 } // namespace content | 1148 } // namespace content |
OLD | NEW |