Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(264)

Side by Side Diff: content/browser/devtools/devtools_http_handler_impl.cc

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

Powered by Google App Engine
This is Rietveld 408576698