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

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: 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/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
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 int connection_id) 411 int connection_id)
160 : message_loop_(message_loop), 412 : message_loop_(message_loop),
161 server_(server), 413 server_wrapper_(server_wrapper),
162 connection_id_(connection_id), 414 connection_id_(connection_id),
163 tracing_handler_(new devtools::tracing::TracingHandler( 415 tracing_handler_(new devtools::tracing::TracingHandler(
164 devtools::tracing::TracingHandler::Browser)), 416 devtools::tracing::TracingHandler::Browser)),
165 protocol_handler_(new DevToolsProtocolHandlerImpl()) { 417 protocol_handler_(new DevToolsProtocolHandlerImpl()) {
166 protocol_handler_->SetNotifier( 418 protocol_handler_->SetNotifier(
167 base::Bind(&BrowserTarget::Respond, base::Unretained(this))); 419 base::Bind(&BrowserTarget::Respond, base::Unretained(this)));
168 protocol_handler_->SetTracingHandler(tracing_handler_.get()); 420 protocol_handler_->SetTracingHandler(tracing_handler_.get());
169 } 421 }
170 422
171 ~BrowserTarget() { 423 ~BrowserTarget() {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
203 Respond(response->Serialize()); 455 Respond(response->Serialize());
204 } else { 456 } else {
205 Respond(command->NoSuchMethodErrorResponse()->Serialize()); 457 Respond(command->NoSuchMethodErrorResponse()->Serialize());
206 } 458 }
207 } 459 }
208 460
209 void Respond(const std::string& message) { 461 void Respond(const std::string& message) {
210 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 462 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
211 message_loop_->PostTask( 463 message_loop_->PostTask(
212 FROM_HERE, 464 FROM_HERE,
213 base::Bind(&net::HttpServer::SendOverWebSocket, 465 base::Bind(&ServerWrapper::SendOverWebSocket,
214 base::Unretained(server_), 466 base::Unretained(server_wrapper_),
215 connection_id_, 467 connection_id_,
216 message)); 468 message));
217 } 469 }
218 470
219 private: 471 private:
220 base::MessageLoop* const message_loop_; 472 base::MessageLoop* const message_loop_;
221 net::HttpServer* const server_; 473 ServerWrapper* const server_wrapper_;
222 const int connection_id_; 474 const int connection_id_;
223 scoped_ptr<devtools::tracing::TracingHandler> tracing_handler_; 475 scoped_ptr<devtools::tracing::TracingHandler> tracing_handler_;
224 scoped_ptr<DevToolsProtocolHandlerImpl> protocol_handler_; 476 scoped_ptr<DevToolsProtocolHandlerImpl> protocol_handler_;
225 std::vector<DevToolsProtocol::Handler*> handlers_; 477 std::vector<DevToolsProtocol::Handler*> handlers_;
226 }; 478 };
227 479
480 } // namespace
481
228 // DevToolsHttpHandler ------------------------------------------------------- 482 // DevToolsHttpHandler -------------------------------------------------------
229 483
230 // static 484 // static
231 bool DevToolsHttpHandler::IsSupportedProtocolVersion( 485 bool DevToolsHttpHandler::IsSupportedProtocolVersion(
232 const std::string& version) { 486 const std::string& version) {
233 return devtools::IsSupportedProtocolVersion(version); 487 return devtools::IsSupportedProtocolVersion(version);
234 } 488 }
235 489
236 // static 490 // static
237 int DevToolsHttpHandler::GetFrontendResourceId(const std::string& name) { 491 int DevToolsHttpHandler::GetFrontendResourceId(const std::string& name) {
238 for (size_t i = 0; i < kDevtoolsResourcesSize; ++i) { 492 for (size_t i = 0; i < kDevtoolsResourcesSize; ++i) {
239 if (name == kDevtoolsResources[i].name) 493 if (name == kDevtoolsResources[i].name)
240 return kDevtoolsResources[i].value; 494 return kDevtoolsResources[i].value;
241 } 495 }
242 return -1; 496 return -1;
243 } 497 }
244 498
245 // static 499 // static
246 DevToolsHttpHandler* DevToolsHttpHandler::Start( 500 DevToolsHttpHandler* DevToolsHttpHandler::Start(
247 scoped_ptr<ServerSocketFactory> server_socket_factory, 501 scoped_ptr<ServerSocketFactory> server_socket_factory,
248 const std::string& frontend_url, 502 const std::string& frontend_url,
249 DevToolsHttpHandlerDelegate* delegate, 503 DevToolsHttpHandlerDelegate* delegate,
250 const base::FilePath& active_port_output_directory) { 504 const base::FilePath& active_port_output_directory) {
251 DevToolsHttpHandlerImpl* http_handler = 505 DevToolsHttpHandlerImpl* http_handler =
252 new DevToolsHttpHandlerImpl(server_socket_factory.Pass(), 506 new DevToolsHttpHandlerImpl(server_socket_factory.Pass(),
253 frontend_url, 507 frontend_url,
254 delegate, 508 delegate,
255 active_port_output_directory); 509 active_port_output_directory);
256 http_handler->Start();
257 return http_handler; 510 return http_handler;
258 } 511 }
259 512
260 // DevToolsHttpHandler::ServerSocketFactory ---------------------------------- 513 // DevToolsHttpHandler::ServerSocketFactory ----------------------------------
261 514
262 DevToolsHttpHandler::ServerSocketFactory::ServerSocketFactory( 515 DevToolsHttpHandler::ServerSocketFactory::ServerSocketFactory(
263 const std::string& address, 516 const std::string& address,
264 int port, 517 int port,
265 int backlog) 518 int backlog)
266 : address_(address), 519 : address_(address),
(...skipping 10 matching lines...) Expand all
277 if (socket && 530 if (socket &&
278 socket->ListenWithAddressAndPort(address_, port_, backlog_) == net::OK) { 531 socket->ListenWithAddressAndPort(address_, port_, backlog_) == net::OK) {
279 return socket.Pass(); 532 return socket.Pass();
280 } 533 }
281 return scoped_ptr<net::ServerSocket>(); 534 return scoped_ptr<net::ServerSocket>();
282 } 535 }
283 536
284 // DevToolsHttpHandlerImpl --------------------------------------------------- 537 // DevToolsHttpHandlerImpl ---------------------------------------------------
285 538
286 DevToolsHttpHandlerImpl::~DevToolsHttpHandlerImpl() { 539 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_); 540 STLDeleteValues(&target_map_);
292 } 541 STLDeleteValues(&browser_targets_);
293 542 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 } 543 }
328 544
329 void DevToolsHttpHandlerImpl::Stop() { 545 void DevToolsHttpHandlerImpl::Stop() {
330 if (!thread_) 546 TerminateOnUI(thread_, server_wrapper_);
331 return; 547 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 } 548 }
346 549
347 GURL DevToolsHttpHandlerImpl::GetFrontendURL() { 550 GURL DevToolsHttpHandlerImpl::GetFrontendURL() {
348 if (!server_ip_address_) 551 if (!server_ip_address_)
349 return GURL(); 552 return GURL();
350 return GURL(std::string("http://") + server_ip_address_->ToString() + frontend _url_); 553 return GURL(std::string("http://") + server_ip_address_->ToString() + frontend _url_);
351 } 554 }
352 555
353 static std::string PathWithoutParams(const std::string& path) { 556 static std::string PathWithoutParams(const std::string& path) {
354 size_t query_position = path.find("?"); 557 size_t query_position = path.find("?");
(...skipping 16 matching lines...) Expand all
371 } else if (EndsWith(filename, ".json", false)) { 574 } else if (EndsWith(filename, ".json", false)) {
372 return "application/json"; 575 return "application/json";
373 } 576 }
374 LOG(ERROR) << "GetMimeType doesn't know mime type for: " 577 LOG(ERROR) << "GetMimeType doesn't know mime type for: "
375 << filename 578 << filename
376 << " text/plain will be returned"; 579 << " text/plain will be returned";
377 NOTREACHED(); 580 NOTREACHED();
378 return "text/plain"; 581 return "text/plain";
379 } 582 }
380 583
381 void DevToolsHttpHandlerImpl::OnHttpRequest( 584 void ServerWrapper::OnHttpRequest(int connection_id,
382 int connection_id, 585 const net::HttpServerRequestInfo& info) {
383 const net::HttpServerRequestInfo& info) {
384 server_->SetSendBufferSize(connection_id, kSendBufferSizeForDevTools); 586 server_->SetSendBufferSize(connection_id, kSendBufferSizeForDevTools);
385 587
386 if (info.path.find("/json") == 0) { 588 if (info.path.find("/json") == 0) {
387 BrowserThread::PostTask( 589 BrowserThread::PostTask(
388 BrowserThread::UI, 590 BrowserThread::UI,
389 FROM_HERE, 591 FROM_HERE,
390 base::Bind(&DevToolsHttpHandlerImpl::OnJsonRequestUI, 592 base::Bind(&DevToolsHttpHandlerImpl::OnJsonRequest,
391 this, 593 handler_,
392 connection_id, 594 connection_id,
393 info)); 595 info));
394 return; 596 return;
395 } 597 }
396 598
397 if (info.path.find(kThumbUrlPrefix) == 0) { 599 if (info.path.find(kThumbUrlPrefix) == 0) {
398 // Thumbnail request. 600 // Thumbnail request.
399 const std::string target_id = info.path.substr(strlen(kThumbUrlPrefix)); 601 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( 602 BrowserThread::PostTask(
405 BrowserThread::UI, 603 BrowserThread::UI,
406 FROM_HERE, 604 FROM_HERE,
407 base::Bind(&DevToolsHttpHandlerImpl::OnThumbnailRequestUI, 605 base::Bind(&DevToolsHttpHandlerImpl::OnThumbnailRequest,
408 this, 606 handler_,
409 connection_id, 607 connection_id,
410 page_url)); 608 target_id));
411 return; 609 return;
412 } 610 }
413 611
414 if (info.path == "" || info.path == "/") { 612 if (info.path == "" || info.path == "/") {
415 // Discovery page request. 613 // Discovery page request.
416 BrowserThread::PostTask( 614 BrowserThread::PostTask(
417 BrowserThread::UI, 615 BrowserThread::UI,
418 FROM_HERE, 616 FROM_HERE,
419 base::Bind(&DevToolsHttpHandlerImpl::OnDiscoveryPageRequestUI, 617 base::Bind(&DevToolsHttpHandlerImpl::OnDiscoveryPageRequest,
420 this, 618 handler_,
421 connection_id)); 619 connection_id));
422 return; 620 return;
423 } 621 }
424 622
425 if (info.path.find("/devtools/") != 0) { 623 if (info.path.find("/devtools/") != 0) {
426 server_->Send404(connection_id); 624 server_->Send404(connection_id);
427 return; 625 return;
428 } 626 }
429 627
430 std::string filename = PathWithoutParams(info.path.substr(10)); 628 std::string filename = PathWithoutParams(info.path.substr(10));
431 std::string mime_type = GetMimeType(filename); 629 std::string mime_type = GetMimeType(filename);
432 630
433 base::FilePath frontend_dir = delegate_->GetDebugFrontendDir(); 631 if (!frontend_dir_.empty()) {
434 if (!frontend_dir.empty()) { 632 base::FilePath path = frontend_dir_.AppendASCII(filename);
435 base::FilePath path = frontend_dir.AppendASCII(filename);
436 std::string data; 633 std::string data;
437 base::ReadFileToString(path, &data); 634 base::ReadFileToString(path, &data);
438 server_->Send200(connection_id, data, mime_type); 635 server_->Send200(connection_id, data, mime_type);
439 return; 636 return;
440 } 637 }
441 if (delegate_->BundlesFrontendResources()) { 638 if (bundles_resources_) {
442 int resource_id = DevToolsHttpHandler::GetFrontendResourceId(filename); 639 int resource_id = DevToolsHttpHandler::GetFrontendResourceId(filename);
443 if (resource_id != -1) { 640 if (resource_id != -1) {
444 base::StringPiece data = GetContentClient()->GetDataResource( 641 base::StringPiece data = GetContentClient()->GetDataResource(
445 resource_id, ui::SCALE_FACTOR_NONE); 642 resource_id, ui::SCALE_FACTOR_NONE);
446 server_->Send200(connection_id, data.as_string(), mime_type); 643 server_->Send200(connection_id, data.as_string(), mime_type);
447 return; 644 return;
448 } 645 }
449 } 646 }
450 server_->Send404(connection_id); 647 server_->Send404(connection_id);
451 } 648 }
452 649
453 void DevToolsHttpHandlerImpl::OnWebSocketRequest( 650 void ServerWrapper::OnWebSocketRequest(
454 int connection_id, 651 int connection_id,
455 const net::HttpServerRequestInfo& request) { 652 const net::HttpServerRequestInfo& request) {
456 BrowserThread::PostTask( 653 BrowserThread::PostTask(
457 BrowserThread::UI, 654 BrowserThread::UI,
458 FROM_HERE, 655 FROM_HERE,
459 base::Bind( 656 base::Bind(
460 &DevToolsHttpHandlerImpl::OnWebSocketRequestUI, 657 &DevToolsHttpHandlerImpl::OnWebSocketRequest,
461 this, 658 handler_,
462 connection_id, 659 connection_id,
463 request)); 660 request));
464 } 661 }
465 662
466 void DevToolsHttpHandlerImpl::OnWebSocketMessage( 663 void ServerWrapper::OnWebSocketMessage(int connection_id,
467 int connection_id, 664 const std::string& data) {
468 const std::string& data) {
469 BrowserThread::PostTask( 665 BrowserThread::PostTask(
470 BrowserThread::UI, 666 BrowserThread::UI,
471 FROM_HERE, 667 FROM_HERE,
472 base::Bind( 668 base::Bind(
473 &DevToolsHttpHandlerImpl::OnWebSocketMessageUI, 669 &DevToolsHttpHandlerImpl::OnWebSocketMessage,
474 this, 670 handler_,
475 connection_id, 671 connection_id,
476 data)); 672 data));
477 } 673 }
478 674
479 void DevToolsHttpHandlerImpl::OnClose(int connection_id) { 675 void ServerWrapper::OnClose(int connection_id) {
480 BrowserThread::PostTask( 676 BrowserThread::PostTask(
481 BrowserThread::UI, 677 BrowserThread::UI,
482 FROM_HERE, 678 FROM_HERE,
483 base::Bind( 679 base::Bind(
484 &DevToolsHttpHandlerImpl::OnCloseUI, 680 &DevToolsHttpHandlerImpl::OnClose,
485 this, 681 handler_,
486 connection_id)); 682 connection_id));
487 } 683 }
488 684
489 std::string DevToolsHttpHandlerImpl::GetFrontendURLInternal( 685 std::string DevToolsHttpHandlerImpl::GetFrontendURLInternal(
490 const std::string id, 686 const std::string id,
491 const std::string& host) { 687 const std::string& host) {
492 return base::StringPrintf( 688 return base::StringPrintf(
493 "%s%sws=%s%s%s", 689 "%s%sws=%s%s%s",
494 frontend_url_.c_str(), 690 frontend_url_.c_str(),
495 frontend_url_.find("?") == std::string::npos ? "?" : "&", 691 frontend_url_.find("?") == std::string::npos ? "?" : "&",
(...skipping 20 matching lines...) Expand all
516 *command = path.substr(1); 712 *command = path.substr(1);
517 713
518 size_t separator_pos = command->find("/"); 714 size_t separator_pos = command->find("/");
519 if (separator_pos != std::string::npos) { 715 if (separator_pos != std::string::npos) {
520 *target_id = command->substr(separator_pos + 1); 716 *target_id = command->substr(separator_pos + 1);
521 *command = command->substr(0, separator_pos); 717 *command = command->substr(0, separator_pos);
522 } 718 }
523 return true; 719 return true;
524 } 720 }
525 721
526 void DevToolsHttpHandlerImpl::OnJsonRequestUI( 722 void DevToolsHttpHandlerImpl::OnJsonRequest(
527 int connection_id, 723 int connection_id,
528 const net::HttpServerRequestInfo& info) { 724 const net::HttpServerRequestInfo& info) {
529 // Trim /json 725 // Trim /json
530 std::string path = info.path.substr(5); 726 std::string path = info.path.substr(5);
531 727
532 // Trim fragment and query 728 // Trim fragment and query
533 std::string query; 729 std::string query;
534 size_t query_pos = path.find("?"); 730 size_t query_pos = path.find("?");
535 if (query_pos != std::string::npos) { 731 if (query_pos != std::string::npos) {
536 query = path.substr(query_pos + 1); 732 query = path.substr(query_pos + 1);
(...skipping 23 matching lines...) Expand all
560 #if defined(OS_ANDROID) 756 #if defined(OS_ANDROID)
561 version.SetString("Android-Package", 757 version.SetString("Android-Package",
562 base::android::BuildInfo::GetInstance()->package_name()); 758 base::android::BuildInfo::GetInstance()->package_name());
563 #endif 759 #endif
564 SendJson(connection_id, net::HTTP_OK, &version, std::string()); 760 SendJson(connection_id, net::HTTP_OK, &version, std::string());
565 return; 761 return;
566 } 762 }
567 763
568 if (command == "list") { 764 if (command == "list") {
569 std::string host = info.headers["host"]; 765 std::string host = info.headers["host"];
570 AddRef(); // Balanced in OnTargetListReceived.
571 DevToolsManagerDelegate* manager_delegate = 766 DevToolsManagerDelegate* manager_delegate =
572 DevToolsManager::GetInstance()->delegate(); 767 DevToolsManager::GetInstance()->delegate();
573 if (manager_delegate) { 768 if (manager_delegate) {
574 manager_delegate->EnumerateTargets( 769 manager_delegate->EnumerateTargets(
575 base::Bind(&DevToolsHttpHandlerImpl::OnTargetListReceived, 770 base::Bind(&DevToolsHttpHandlerImpl::OnTargetListReceivedWeak,
576 this, connection_id, host)); 771 weak_factory_.GetWeakPtr(), connection_id, host));
577 } else { 772 } else {
578 DevToolsManagerDelegate::TargetList empty_list; 773 DevToolsManagerDelegate::TargetList empty_list;
579 OnTargetListReceived(connection_id, host, empty_list); 774 OnTargetListReceived(connection_id, host, empty_list);
580 } 775 }
581 return; 776 return;
582 } 777 }
583 778
584 if (command == "new") { 779 if (command == "new") {
585 GURL url(net::UnescapeURLComponent( 780 GURL url(net::UnescapeURLComponent(
586 query, net::UnescapeRule::URL_SPECIAL_CHARS)); 781 query, net::UnescapeRule::URL_SPECIAL_CHARS));
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
641 return; 836 return;
642 } 837 }
643 } 838 }
644 SendJson(connection_id, 839 SendJson(connection_id,
645 net::HTTP_NOT_FOUND, 840 net::HTTP_NOT_FOUND,
646 NULL, 841 NULL,
647 "Unknown command: " + command); 842 "Unknown command: " + command);
648 return; 843 return;
649 } 844 }
650 845
846 // static
847 void DevToolsHttpHandlerImpl::OnTargetListReceivedWeak(
848 base::WeakPtr<DevToolsHttpHandlerImpl> handler,
849 int connection_id,
850 const std::string& host,
851 const DevToolsManagerDelegate::TargetList& targets) {
852 if (handler) {
853 handler->OnTargetListReceived(connection_id, host, targets);
854 } else {
855 STLDeleteContainerPointers(targets.begin(), targets.end());
856 }
857 }
858
651 void DevToolsHttpHandlerImpl::OnTargetListReceived( 859 void DevToolsHttpHandlerImpl::OnTargetListReceived(
652 int connection_id, 860 int connection_id,
653 const std::string& host, 861 const std::string& host,
654 const DevToolsManagerDelegate::TargetList& targets) { 862 const DevToolsManagerDelegate::TargetList& targets) {
655 DevToolsManagerDelegate::TargetList sorted_targets = targets; 863 DevToolsManagerDelegate::TargetList sorted_targets = targets;
656 std::sort(sorted_targets.begin(), sorted_targets.end(), TimeComparator); 864 std::sort(sorted_targets.begin(), sorted_targets.end(), TimeComparator);
657 865
658 STLDeleteValues(&target_map_); 866 STLDeleteValues(&target_map_);
659 base::ListValue list_value; 867 base::ListValue list_value;
660 for (DevToolsManagerDelegate::TargetList::const_iterator it = 868 for (DevToolsManagerDelegate::TargetList::const_iterator it =
661 sorted_targets.begin(); it != sorted_targets.end(); ++it) { 869 sorted_targets.begin(); it != sorted_targets.end(); ++it) {
662 DevToolsTarget* target = *it; 870 DevToolsTarget* target = *it;
663 target_map_[target->GetId()] = target; 871 target_map_[target->GetId()] = target;
664 list_value.Append(SerializeTarget(*target, host)); 872 list_value.Append(SerializeTarget(*target, host));
665 } 873 }
666 SendJson(connection_id, net::HTTP_OK, &list_value, std::string()); 874 SendJson(connection_id, net::HTTP_OK, &list_value, std::string());
667 Release(); // Balanced in OnJsonRequestUI.
668 } 875 }
669 876
670 DevToolsTarget* DevToolsHttpHandlerImpl::GetTarget(const std::string& id) { 877 DevToolsTarget* DevToolsHttpHandlerImpl::GetTarget(const std::string& id) {
671 TargetMap::const_iterator it = target_map_.find(id); 878 TargetMap::const_iterator it = target_map_.find(id);
672 if (it == target_map_.end()) 879 if (it == target_map_.end())
673 return NULL; 880 return NULL;
674 return it->second; 881 return it->second;
675 } 882 }
676 883
677 void DevToolsHttpHandlerImpl::OnThumbnailRequestUI( 884 void DevToolsHttpHandlerImpl::OnThumbnailRequest(
678 int connection_id, const GURL& page_url) { 885 int connection_id, const std::string& target_id) {
886 DevToolsTarget* target = GetTarget(target_id);
887 GURL page_url;
888 if (target)
889 page_url = target->GetURL();
679 DevToolsManagerDelegate* manager_delegate = 890 DevToolsManagerDelegate* manager_delegate =
680 DevToolsManager::GetInstance()->delegate(); 891 DevToolsManager::GetInstance()->delegate();
681 std::string data = 892 std::string data =
682 manager_delegate ? manager_delegate->GetPageThumbnailData(page_url) : ""; 893 manager_delegate ? manager_delegate->GetPageThumbnailData(page_url) : "";
683 if (!data.empty()) 894 if (!data.empty())
684 Send200(connection_id, data, "image/png"); 895 Send200(connection_id, data, "image/png");
685 else 896 else
686 Send404(connection_id); 897 Send404(connection_id);
687 } 898 }
688 899
689 void DevToolsHttpHandlerImpl::OnDiscoveryPageRequestUI(int connection_id) { 900 void DevToolsHttpHandlerImpl::OnDiscoveryPageRequest(int connection_id) {
690 std::string response = delegate_->GetDiscoveryPageHTML(); 901 std::string response = delegate_->GetDiscoveryPageHTML();
691 Send200(connection_id, response, "text/html; charset=UTF-8"); 902 Send200(connection_id, response, "text/html; charset=UTF-8");
692 } 903 }
693 904
694 void DevToolsHttpHandlerImpl::OnWebSocketRequestUI( 905 void DevToolsHttpHandlerImpl::OnWebSocketRequest(
695 int connection_id, 906 int connection_id,
696 const net::HttpServerRequestInfo& request) { 907 const net::HttpServerRequestInfo& request) {
697 if (!thread_) 908 if (!thread_)
698 return; 909 return;
699 910
700 std::string browser_prefix = "/devtools/browser"; 911 std::string browser_prefix = "/devtools/browser";
701 size_t browser_pos = request.path.find(browser_prefix); 912 size_t browser_pos = request.path.find(browser_prefix);
702 if (browser_pos == 0) { 913 if (browser_pos == 0) {
703 BrowserTarget* browser_target = new BrowserTarget( 914 BrowserTarget* browser_target = new BrowserTarget(
704 thread_->message_loop(), server_.get(), connection_id); 915 thread_->message_loop(), server_wrapper_, connection_id);
705 browser_target->RegisterHandler( 916 browser_target->RegisterHandler(
706 new TetheringHandler(delegate_.get(), thread_->message_loop_proxy())); 917 new TetheringHandler(delegate_.get(), thread_->message_loop_proxy()));
707 browser_target->RegisterHandler( 918 browser_target->RegisterHandler(
708 new DevToolsSystemInfoHandler()); 919 new DevToolsSystemInfoHandler());
709 browser_targets_[connection_id] = browser_target; 920 browser_targets_[connection_id] = browser_target;
710 AcceptWebSocket(connection_id, request); 921 AcceptWebSocket(connection_id, request);
711 return; 922 return;
712 } 923 }
713 924
714 size_t pos = request.path.find(kPageUrlPrefix); 925 size_t pos = request.path.find(kPageUrlPrefix);
(...skipping 11 matching lines...) Expand all
726 return; 937 return;
727 } 938 }
728 939
729 if (agent->IsAttached()) { 940 if (agent->IsAttached()) {
730 Send500(connection_id, 941 Send500(connection_id,
731 "Target with given id is being inspected: " + page_id); 942 "Target with given id is being inspected: " + page_id);
732 return; 943 return;
733 } 944 }
734 945
735 DevToolsAgentHostClientImpl* client_host = new DevToolsAgentHostClientImpl( 946 DevToolsAgentHostClientImpl* client_host = new DevToolsAgentHostClientImpl(
736 thread_->message_loop(), server_.get(), connection_id, agent.get()); 947 thread_->message_loop(), server_wrapper_, connection_id, agent.get());
737 connection_to_client_ui_[connection_id] = client_host; 948 connection_to_client_[connection_id] = client_host;
738 949
739 AcceptWebSocket(connection_id, request); 950 AcceptWebSocket(connection_id, request);
740 } 951 }
741 952
742 void DevToolsHttpHandlerImpl::OnWebSocketMessageUI( 953 void DevToolsHttpHandlerImpl::OnWebSocketMessage(
743 int connection_id, 954 int connection_id,
744 const std::string& data) { 955 const std::string& data) {
745 BrowserTargets::iterator browser_it = browser_targets_.find(connection_id); 956 BrowserTargets::iterator browser_it = browser_targets_.find(connection_id);
746 if (browser_it != browser_targets_.end()) { 957 if (browser_it != browser_targets_.end()) {
747 browser_it->second->HandleMessage(data); 958 browser_it->second->HandleMessage(data);
748 return; 959 return;
749 } 960 }
750 961
751 ConnectionToClientMap::iterator it = 962 ConnectionToClientMap::iterator it =
752 connection_to_client_ui_.find(connection_id); 963 connection_to_client_.find(connection_id);
753 if (it == connection_to_client_ui_.end()) 964 if (it != connection_to_client_.end())
754 return; 965 it->second->OnMessage(data);
755
756 DevToolsAgentHostClientImpl* client =
757 static_cast<DevToolsAgentHostClientImpl*>(it->second);
758 client->OnMessage(data);
759 } 966 }
760 967
761 void DevToolsHttpHandlerImpl::OnCloseUI(int connection_id) { 968 void DevToolsHttpHandlerImpl::OnClose(int connection_id) {
762 BrowserTargets::iterator browser_it = browser_targets_.find(connection_id); 969 BrowserTargets::iterator browser_it = browser_targets_.find(connection_id);
763 if (browser_it != browser_targets_.end()) { 970 if (browser_it != browser_targets_.end()) {
764 delete browser_it->second; 971 delete browser_it->second;
765 browser_targets_.erase(connection_id); 972 browser_targets_.erase(connection_id);
766 return; 973 return;
767 } 974 }
768 975
769 ConnectionToClientMap::iterator it = 976 ConnectionToClientMap::iterator it =
770 connection_to_client_ui_.find(connection_id); 977 connection_to_client_.find(connection_id);
771 if (it != connection_to_client_ui_.end()) { 978 if (it != connection_to_client_.end()) {
772 DevToolsAgentHostClientImpl* client = 979 delete it->second;
773 static_cast<DevToolsAgentHostClientImpl*>(it->second); 980 connection_to_client_.erase(connection_id);
774 delete client;
775 connection_to_client_ui_.erase(connection_id);
776 } 981 }
777 } 982 }
778 983
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( 984 DevToolsHttpHandlerImpl::DevToolsHttpHandlerImpl(
785 scoped_ptr<ServerSocketFactory> server_socket_factory, 985 scoped_ptr<ServerSocketFactory> server_socket_factory,
786 const std::string& frontend_url, 986 const std::string& frontend_url,
787 DevToolsHttpHandlerDelegate* delegate, 987 DevToolsHttpHandlerDelegate* delegate,
788 const base::FilePath& active_port_output_directory) 988 const base::FilePath& output_directory)
789 : frontend_url_(frontend_url), 989 : thread_(nullptr),
790 server_socket_factory_(server_socket_factory.Pass()), 990 frontend_url_(frontend_url),
991 server_wrapper_(nullptr),
791 delegate_(delegate), 992 delegate_(delegate),
792 active_port_output_directory_(active_port_output_directory) { 993 weak_factory_(this) {
793 if (frontend_url_.empty()) 994 if (frontend_url_.empty())
794 frontend_url_ = "/devtools/devtools.html"; 995 frontend_url_ = "/devtools/devtools.html";
795 996
796 // Balanced in ResetHandlerThreadAndRelease(). 997 BrowserThread::PostTask(
797 AddRef(); 998 BrowserThread::FILE, FROM_HERE,
999 base::Bind(&StartServerOnFile,
1000 weak_factory_.GetWeakPtr(),
1001 base::Passed(&server_socket_factory),
1002 output_directory,
1003 delegate_->GetDebugFrontendDir(),
1004 delegate_->BundlesFrontendResources()));
798 } 1005 }
799 1006
800 // Runs on the handler thread 1007 void DevToolsHttpHandlerImpl::ServerStarted(
801 void DevToolsHttpHandlerImpl::Init() { 1008 base::Thread* thread,
802 scoped_ptr<net::ServerSocket> server_socket = 1009 ServerWrapper* server_wrapper,
803 server_socket_factory_->CreateAndListen(); 1010 scoped_ptr<net::IPEndPoint> ip_address) {
804 if (!server_socket) { 1011 thread_ = thread;
805 LOG(ERROR) << "Cannot start http server for devtools. Stop devtools."; 1012 server_wrapper_ = server_wrapper;
806 BrowserThread::PostTask( 1013 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 } 1014 }
822 1015
823 // Runs on the handler thread 1016 void ServerWrapper::WriteActivePortToUserProfile(
824 void DevToolsHttpHandlerImpl::Teardown() { 1017 const base::FilePath& output_directory) {
825 server_.reset(); 1018 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; 1019 net::IPEndPoint endpoint;
843 int err; 1020 int err;
844 if ((err = server_->GetLocalAddress(&endpoint)) != net::OK) { 1021 if ((err = server_->GetLocalAddress(&endpoint)) != net::OK) {
845 LOG(ERROR) << "Error " << err << " getting local address"; 1022 LOG(ERROR) << "Error " << err << " getting local address";
846 return; 1023 return;
847 } 1024 }
848 1025
849 // Write this port to a well-known file in the profile directory 1026 // Write this port to a well-known file in the profile directory
850 // so Telemetry can pick it up. 1027 // so Telemetry can pick it up.
851 base::FilePath path = active_port_output_directory_.Append( 1028 base::FilePath path = output_directory.Append(kDevToolsActivePortFileName);
852 kDevToolsActivePortFileName);
853 std::string port_string = base::IntToString(endpoint.port()); 1029 std::string port_string = base::IntToString(endpoint.port());
854 if (base::WriteFile(path, port_string.c_str(), port_string.length()) < 0) { 1030 if (base::WriteFile(path, port_string.c_str(), port_string.length()) < 0) {
855 LOG(ERROR) << "Error writing DevTools active port to file"; 1031 LOG(ERROR) << "Error writing DevTools active port to file";
856 } 1032 }
857 } 1033 }
858 1034
859 void DevToolsHttpHandlerImpl::SendJson(int connection_id, 1035 void DevToolsHttpHandlerImpl::SendJson(int connection_id,
860 net::HttpStatusCode status_code, 1036 net::HttpStatusCode status_code,
861 base::Value* value, 1037 base::Value* value,
862 const std::string& message) { 1038 const std::string& message) {
863 if (!thread_) 1039 if (!thread_)
864 return; 1040 return;
865 1041
866 // Serialize value and message. 1042 // Serialize value and message.
867 std::string json_value; 1043 std::string json_value;
868 if (value) { 1044 if (value) {
869 base::JSONWriter::WriteWithOptions(value, 1045 base::JSONWriter::WriteWithOptions(value,
870 base::JSONWriter::OPTIONS_PRETTY_PRINT, 1046 base::JSONWriter::OPTIONS_PRETTY_PRINT,
871 &json_value); 1047 &json_value);
872 } 1048 }
873 std::string json_message; 1049 std::string json_message;
874 scoped_ptr<base::Value> message_object(new base::StringValue(message)); 1050 scoped_ptr<base::Value> message_object(new base::StringValue(message));
875 base::JSONWriter::Write(message_object.get(), &json_message); 1051 base::JSONWriter::Write(message_object.get(), &json_message);
876 1052
877 net::HttpServerResponseInfo response(status_code); 1053 net::HttpServerResponseInfo response(status_code);
878 response.SetBody(json_value + message, "application/json; charset=UTF-8"); 1054 response.SetBody(json_value + message, "application/json; charset=UTF-8");
879 1055
880 thread_->message_loop()->PostTask( 1056 thread_->message_loop()->PostTask(
881 FROM_HERE, 1057 FROM_HERE,
882 base::Bind(&net::HttpServer::SendResponse, 1058 base::Bind(&ServerWrapper::SendResponse,
883 base::Unretained(server_.get()), 1059 base::Unretained(server_wrapper_),
884 connection_id, 1060 connection_id,
885 response)); 1061 response));
886 } 1062 }
887 1063
888 void DevToolsHttpHandlerImpl::Send200(int connection_id, 1064 void DevToolsHttpHandlerImpl::Send200(int connection_id,
889 const std::string& data, 1065 const std::string& data,
890 const std::string& mime_type) { 1066 const std::string& mime_type) {
891 if (!thread_) 1067 if (!thread_)
892 return; 1068 return;
893 thread_->message_loop()->PostTask( 1069 thread_->message_loop()->PostTask(
894 FROM_HERE, 1070 FROM_HERE,
895 base::Bind(&net::HttpServer::Send200, 1071 base::Bind(&ServerWrapper::Send200,
896 base::Unretained(server_.get()), 1072 base::Unretained(server_wrapper_),
897 connection_id, 1073 connection_id,
898 data, 1074 data,
899 mime_type)); 1075 mime_type));
900 } 1076 }
901 1077
902 void DevToolsHttpHandlerImpl::Send404(int connection_id) { 1078 void DevToolsHttpHandlerImpl::Send404(int connection_id) {
903 if (!thread_) 1079 if (!thread_)
904 return; 1080 return;
905 thread_->message_loop()->PostTask( 1081 thread_->message_loop()->PostTask(
906 FROM_HERE, 1082 FROM_HERE,
907 base::Bind(&net::HttpServer::Send404, 1083 base::Bind(&ServerWrapper::Send404,
908 base::Unretained(server_.get()), 1084 base::Unretained(server_wrapper_),
909 connection_id)); 1085 connection_id));
910 } 1086 }
911 1087
912 void DevToolsHttpHandlerImpl::Send500(int connection_id, 1088 void DevToolsHttpHandlerImpl::Send500(int connection_id,
913 const std::string& message) { 1089 const std::string& message) {
914 if (!thread_) 1090 if (!thread_)
915 return; 1091 return;
916 thread_->message_loop()->PostTask( 1092 thread_->message_loop()->PostTask(
917 FROM_HERE, 1093 FROM_HERE,
918 base::Bind(&net::HttpServer::Send500, 1094 base::Bind(&ServerWrapper::Send500,
919 base::Unretained(server_.get()), 1095 base::Unretained(server_wrapper_),
920 connection_id, 1096 connection_id,
921 message)); 1097 message));
922 } 1098 }
923 1099
924 void DevToolsHttpHandlerImpl::AcceptWebSocket( 1100 void DevToolsHttpHandlerImpl::AcceptWebSocket(
925 int connection_id, 1101 int connection_id,
926 const net::HttpServerRequestInfo& request) { 1102 const net::HttpServerRequestInfo& request) {
927 if (!thread_) 1103 if (!thread_)
928 return; 1104 return;
929 thread_->message_loop()->PostTask( 1105 thread_->message_loop()->PostTask(
930 FROM_HERE, 1106 FROM_HERE,
931 base::Bind(&net::HttpServer::SetSendBufferSize, 1107 base::Bind(&ServerWrapper::AcceptWebSocket,
932 base::Unretained(server_.get()), 1108 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, 1109 connection_id,
940 request)); 1110 request));
941 } 1111 }
942 1112
943 base::DictionaryValue* DevToolsHttpHandlerImpl::SerializeTarget( 1113 base::DictionaryValue* DevToolsHttpHandlerImpl::SerializeTarget(
944 const DevToolsTarget& target, 1114 const DevToolsTarget& target,
945 const std::string& host) { 1115 const std::string& host) {
946 base::DictionaryValue* dictionary = new base::DictionaryValue; 1116 base::DictionaryValue* dictionary = new base::DictionaryValue;
947 1117
948 std::string id = target.GetId(); 1118 std::string id = target.GetId();
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
980 id.c_str(), 1150 id.c_str(),
981 host); 1151 host);
982 dictionary->SetString( 1152 dictionary->SetString(
983 kTargetDevtoolsFrontendUrlField, devtools_frontend_url); 1153 kTargetDevtoolsFrontendUrlField, devtools_frontend_url);
984 } 1154 }
985 1155
986 return dictionary; 1156 return dictionary;
987 } 1157 }
988 1158
989 } // namespace content 1159 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698