OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/debugger/devtools_http_handler_impl.h" | 5 #include "content/browser/debugger/devtools_http_handler_impl.h" |
6 | 6 |
7 #include <algorithm> | |
7 #include <utility> | 8 #include <utility> |
8 | 9 |
9 #include "base/bind.h" | 10 #include "base/bind.h" |
10 #include "base/compiler_specific.h" | 11 #include "base/compiler_specific.h" |
11 #include "base/json/json_writer.h" | 12 #include "base/json/json_writer.h" |
12 #include "base/lazy_instance.h" | 13 #include "base/lazy_instance.h" |
13 #include "base/logging.h" | 14 #include "base/logging.h" |
14 #include "base/message_loop_proxy.h" | 15 #include "base/message_loop_proxy.h" |
15 #include "base/string_number_conversions.h" | 16 #include "base/string_number_conversions.h" |
16 #include "base/stringprintf.h" | 17 #include "base/stringprintf.h" |
(...skipping 20 matching lines...) Expand all Loading... | |
37 #include "net/server/http_server_request_info.h" | 38 #include "net/server/http_server_request_info.h" |
38 #include "net/url_request/url_request_context.h" | 39 #include "net/url_request/url_request_context.h" |
39 #include "net/url_request/url_request_context_getter.h" | 40 #include "net/url_request/url_request_context_getter.h" |
40 | 41 |
41 namespace content { | 42 namespace content { |
42 | 43 |
43 const int kBufferSize = 16 * 1024; | 44 const int kBufferSize = 16 * 1024; |
44 | 45 |
45 namespace { | 46 namespace { |
46 | 47 |
48 class DevToolsDefaultBindingHandler | |
49 : public DevToolsHttpHandlerDelegate::BindingHandler { | |
50 public: | |
51 DevToolsDefaultBindingHandler() { | |
52 } | |
53 | |
54 virtual std::string GetRenderViewHostIdentifier( | |
55 RenderViewHost* rvh) OVERRIDE { | |
56 Target target = std::make_pair(rvh->GetProcess()->GetID(), | |
57 rvh->GetRoutingID()); | |
58 targets_.push_back(target); | |
59 size_t index = targets_.size() - 1; | |
60 return base::StringPrintf("%lu", index); | |
pfeldman
2012/04/25 05:45:15
Nit: it might be a good time to migrate to the "<p
Marshall
2012/04/25 15:14:57
Done.
| |
61 } | |
62 | |
63 virtual RenderViewHost* GetRenderViewHostBinding( | |
64 const std::string& identifier) OVERRIDE { | |
65 size_t index; | |
66 if (!base::StringToSizeT(identifier, &index)) | |
67 return NULL; | |
68 if (index >= targets_.size()) | |
69 return NULL; | |
70 | |
71 return RenderViewHost::FromID(targets_[index].first, | |
72 targets_[index].second); | |
73 } | |
74 | |
75 virtual void ResetRenderViewHostBinding() OVERRIDE { | |
76 targets_.clear(); | |
77 } | |
78 | |
79 private: | |
80 typedef std::pair<int, int> Target; | |
81 std::vector<Target> targets_; | |
82 }; | |
83 | |
84 | |
47 // An internal implementation of DevToolsClientHost that delegates | 85 // An internal implementation of DevToolsClientHost that delegates |
48 // messages sent for DevToolsClient to a DebuggerShell instance. | 86 // messages sent for DevToolsClient to a DebuggerShell instance. |
49 class DevToolsClientHostImpl : public DevToolsClientHost { | 87 class DevToolsClientHostImpl : public DevToolsClientHost { |
50 public: | 88 public: |
51 DevToolsClientHostImpl( | 89 DevToolsClientHostImpl( |
52 net::HttpServer* server, | 90 net::HttpServer* server, |
53 int connection_id) | 91 int connection_id) |
54 : server_(server), | 92 : server_(server), |
55 connection_id_(connection_id) { | 93 connection_id_(connection_id) { |
56 } | 94 } |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
255 | 293 |
256 BrowserThread::PostTask( | 294 BrowserThread::PostTask( |
257 BrowserThread::UI, | 295 BrowserThread::UI, |
258 FROM_HERE, | 296 FROM_HERE, |
259 base::Bind( | 297 base::Bind( |
260 &DevToolsHttpHandlerImpl::OnCloseUI, | 298 &DevToolsHttpHandlerImpl::OnCloseUI, |
261 this, | 299 this, |
262 connection_id)); | 300 connection_id)); |
263 } | 301 } |
264 | 302 |
265 struct DevToolsHttpHandlerImpl::PageInfo | 303 struct DevToolsHttpHandlerImpl::PageInfo { |
266 { | |
267 PageInfo() | 304 PageInfo() |
268 : id(0), | 305 : attached(false) { |
269 attached(false) { | |
270 } | 306 } |
271 | 307 |
272 int id; | 308 std::string id; |
273 std::string url; | 309 std::string url; |
274 bool attached; | 310 bool attached; |
275 std::string title; | 311 std::string title; |
276 std::string thumbnail_url; | 312 std::string thumbnail_url; |
277 std::string favicon_url; | 313 std::string favicon_url; |
278 base::TimeTicks last_selected_time; | 314 base::TimeTicks last_selected_time; |
279 }; | 315 }; |
280 | 316 |
281 // static | 317 // static |
282 bool DevToolsHttpHandlerImpl::SortPageListByTime(const PageInfo& info1, | 318 bool DevToolsHttpHandlerImpl::SortPageListByTime(const PageInfo& info1, |
283 const PageInfo& info2) { | 319 const PageInfo& info2) { |
284 return info1.last_selected_time > info2.last_selected_time; | 320 return info1.last_selected_time > info2.last_selected_time; |
285 } | 321 } |
286 | 322 |
287 DevToolsHttpHandlerImpl::PageList DevToolsHttpHandlerImpl::GeneratePageList() { | 323 DevToolsHttpHandlerImpl::PageList DevToolsHttpHandlerImpl::GeneratePageList() { |
288 ResetRenderViewHostBinding(); | 324 binding_handler_->ResetRenderViewHostBinding(); |
289 PageList page_list; | 325 PageList page_list; |
290 for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator()); | 326 for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator()); |
291 !it.IsAtEnd(); it.Advance()) { | 327 !it.IsAtEnd(); it.Advance()) { |
292 RenderProcessHost* render_process_host = it.GetCurrentValue(); | 328 RenderProcessHost* render_process_host = it.GetCurrentValue(); |
293 DCHECK(render_process_host); | 329 DCHECK(render_process_host); |
294 | 330 |
295 // Ignore processes that don't have a connection, such as crashed contents. | 331 // Ignore processes that don't have a connection, such as crashed contents. |
296 if (!render_process_host->HasConnection()) | 332 if (!render_process_host->HasConnection()) |
297 continue; | 333 continue; |
298 | 334 |
299 RenderProcessHost::RenderWidgetHostsIterator rwit( | 335 RenderProcessHost::RenderWidgetHostsIterator rwit( |
300 render_process_host->GetRenderWidgetHostsIterator()); | 336 render_process_host->GetRenderWidgetHostsIterator()); |
301 for (; !rwit.IsAtEnd(); rwit.Advance()) { | 337 for (; !rwit.IsAtEnd(); rwit.Advance()) { |
302 const RenderWidgetHost* widget = rwit.GetCurrentValue(); | 338 const RenderWidgetHost* widget = rwit.GetCurrentValue(); |
303 DCHECK(widget); | 339 DCHECK(widget); |
304 if (!widget || !widget->IsRenderView()) | 340 if (!widget || !widget->IsRenderView()) |
305 continue; | 341 continue; |
306 | 342 |
307 RenderViewHost* host = | 343 RenderViewHost* host = |
308 RenderViewHost::From(const_cast<RenderWidgetHost*>(widget)); | 344 RenderViewHost::From(const_cast<RenderWidgetHost*>(widget)); |
309 content::RenderViewHostDelegate* host_delegate = host->GetDelegate(); | 345 content::RenderViewHostDelegate* host_delegate = host->GetDelegate(); |
310 | 346 |
311 DevToolsAgentHost* agent = | 347 DevToolsAgentHost* agent = |
312 DevToolsAgentHostRegistry::GetDevToolsAgentHost(host); | 348 DevToolsAgentHostRegistry::GetDevToolsAgentHost(host); |
313 DevToolsClientHost* client_host = DevToolsManager::GetInstance()-> | 349 DevToolsClientHost* client_host = DevToolsManager::GetInstance()-> |
314 GetDevToolsClientHostFor(agent); | 350 GetDevToolsClientHostFor(agent); |
315 PageInfo page_info; | 351 PageInfo page_info; |
316 page_info.id = BindRenderViewHost(host); | 352 page_info.id = binding_handler_->GetRenderViewHostIdentifier(host); |
317 page_info.attached = client_host != NULL; | 353 page_info.attached = client_host != NULL; |
318 page_info.url = host_delegate->GetURL().spec(); | 354 page_info.url = host_delegate->GetURL().spec(); |
319 | 355 |
320 WebContents* web_contents = host_delegate->GetAsWebContents(); | 356 WebContents* web_contents = host_delegate->GetAsWebContents(); |
321 if (web_contents) { | 357 if (web_contents) { |
322 page_info.title = UTF16ToUTF8( | 358 page_info.title = UTF16ToUTF8( |
323 net::EscapeForHTML(web_contents->GetTitle())); | 359 net::EscapeForHTML(web_contents->GetTitle())); |
324 page_info.last_selected_time = web_contents->GetLastSelectedTime(); | 360 page_info.last_selected_time = web_contents->GetLastSelectedTime(); |
325 | 361 |
326 NavigationController& controller = web_contents->GetController(); | 362 NavigationController& controller = web_contents->GetController(); |
(...skipping 11 matching lines...) Expand all Loading... | |
338 } | 374 } |
339 | 375 |
340 void DevToolsHttpHandlerImpl::OnJsonRequestUI( | 376 void DevToolsHttpHandlerImpl::OnJsonRequestUI( |
341 int connection_id, | 377 int connection_id, |
342 const net::HttpServerRequestInfo& info) { | 378 const net::HttpServerRequestInfo& info) { |
343 PageList page_list = GeneratePageList(); | 379 PageList page_list = GeneratePageList(); |
344 ListValue json_pages_list; | 380 ListValue json_pages_list; |
345 std::string host = info.headers["Host"]; | 381 std::string host = info.headers["Host"]; |
346 for (PageList::iterator i = page_list.begin(); | 382 for (PageList::iterator i = page_list.begin(); |
347 i != page_list.end(); ++i) { | 383 i != page_list.end(); ++i) { |
348 | |
349 DictionaryValue* page_info = new DictionaryValue; | 384 DictionaryValue* page_info = new DictionaryValue; |
350 json_pages_list.Append(page_info); | 385 json_pages_list.Append(page_info); |
351 page_info->SetString("title", i->title); | 386 page_info->SetString("title", i->title); |
352 page_info->SetString("url", i->url); | 387 page_info->SetString("url", i->url); |
353 page_info->SetString("thumbnailUrl", i->thumbnail_url); | 388 page_info->SetString("thumbnailUrl", i->thumbnail_url); |
354 page_info->SetString("faviconUrl", i->favicon_url); | 389 page_info->SetString("faviconUrl", i->favicon_url); |
355 if (!i->attached) { | 390 if (!i->attached) { |
356 page_info->SetString("webSocketDebuggerUrl", | 391 page_info->SetString("webSocketDebuggerUrl", |
357 base::StringPrintf("ws://%s/devtools/page/%d", | 392 base::StringPrintf("ws://%s/devtools/page/%s", |
358 host.c_str(), | 393 host.c_str(), |
359 i->id)); | 394 i->id.c_str())); |
360 std::string devtools_frontend_url = base::StringPrintf( | 395 std::string devtools_frontend_url = base::StringPrintf( |
361 "%s%sws=%s/devtools/page/%d", | 396 "%s%sws=%s/devtools/page/%s", |
362 overridden_frontend_url_.c_str(), | 397 overridden_frontend_url_.c_str(), |
363 overridden_frontend_url_.find("?") == std::string::npos ? "?" : "&", | 398 overridden_frontend_url_.find("?") == std::string::npos ? "?" : "&", |
364 host.c_str(), | 399 host.c_str(), |
365 i->id); | 400 i->id.c_str()); |
366 page_info->SetString("devtoolsFrontendUrl", devtools_frontend_url); | 401 page_info->SetString("devtoolsFrontendUrl", devtools_frontend_url); |
367 } | 402 } |
368 } | 403 } |
369 | 404 |
370 std::string response; | 405 std::string response; |
371 base::JSONWriter::WriteWithOptions(&json_pages_list, | 406 base::JSONWriter::WriteWithOptions(&json_pages_list, |
372 base::JSONWriter::OPTIONS_PRETTY_PRINT, | 407 base::JSONWriter::OPTIONS_PRETTY_PRINT, |
373 &response); | 408 &response); |
374 Send200(connection_id, response, "application/json; charset=UTF-8"); | 409 Send200(connection_id, response, "application/json; charset=UTF-8"); |
375 } | 410 } |
376 | 411 |
377 void DevToolsHttpHandlerImpl::OnWebSocketRequestUI( | 412 void DevToolsHttpHandlerImpl::OnWebSocketRequestUI( |
378 int connection_id, | 413 int connection_id, |
379 const net::HttpServerRequestInfo& request) { | 414 const net::HttpServerRequestInfo& request) { |
380 std::string prefix = "/devtools/page/"; | 415 std::string prefix = "/devtools/page/"; |
381 size_t pos = request.path.find(prefix); | 416 size_t pos = request.path.find(prefix); |
382 if (pos != 0) { | 417 if (pos != 0) { |
383 Send404(connection_id); | 418 Send404(connection_id); |
384 return; | 419 return; |
385 } | 420 } |
421 | |
386 std::string page_id = request.path.substr(prefix.length()); | 422 std::string page_id = request.path.substr(prefix.length()); |
387 int id = 0; | 423 RenderViewHost* rvh = binding_handler_->GetRenderViewHostBinding(page_id); |
388 if (!base::StringToInt(page_id, &id)) { | |
389 Send500(connection_id, "Invalid page id: " + page_id); | |
390 return; | |
391 } | |
392 | |
393 RenderViewHost* rvh = GetBoundRenderViewHost(id); | |
394 if (!rvh) { | 424 if (!rvh) { |
395 Send500(connection_id, "No such target id: " + page_id); | 425 Send500(connection_id, "No such target id: " + page_id); |
396 return; | 426 return; |
397 } | 427 } |
398 | 428 |
399 DevToolsManager* manager = DevToolsManager::GetInstance(); | 429 DevToolsManager* manager = DevToolsManager::GetInstance(); |
400 DevToolsAgentHost* agent = DevToolsAgentHostRegistry::GetDevToolsAgentHost( | 430 DevToolsAgentHost* agent = DevToolsAgentHostRegistry::GetDevToolsAgentHost( |
401 rvh); | 431 rvh); |
402 if (manager->GetDevToolsClientHostFor(agent)) { | 432 if (manager->GetDevToolsClientHostFor(agent)) { |
403 Send500(connection_id, "Target with given id is being inspected: " + | 433 Send500(connection_id, "Target with given id is being inspected: " + |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
503 net::URLRequestContextGetter* request_context_getter, | 533 net::URLRequestContextGetter* request_context_getter, |
504 DevToolsHttpHandlerDelegate* delegate) | 534 DevToolsHttpHandlerDelegate* delegate) |
505 : ip_(ip), | 535 : ip_(ip), |
506 port_(port), | 536 port_(port), |
507 overridden_frontend_url_(frontend_url), | 537 overridden_frontend_url_(frontend_url), |
508 request_context_getter_(request_context_getter), | 538 request_context_getter_(request_context_getter), |
509 delegate_(delegate) { | 539 delegate_(delegate) { |
510 if (overridden_frontend_url_.empty()) | 540 if (overridden_frontend_url_.empty()) |
511 overridden_frontend_url_ = "/devtools/devtools.html"; | 541 overridden_frontend_url_ = "/devtools/devtools.html"; |
512 | 542 |
543 binding_handler_.reset(delegate_->GetBindingHandler()); | |
544 if (!binding_handler_.get()) | |
545 binding_handler_.reset(new DevToolsDefaultBindingHandler); | |
546 | |
513 AddRef(); | 547 AddRef(); |
514 } | 548 } |
515 | 549 |
516 void DevToolsHttpHandlerImpl::Init() { | 550 void DevToolsHttpHandlerImpl::Init() { |
517 server_ = new net::HttpServer(ip_, port_, this); | 551 server_ = new net::HttpServer(ip_, port_, this); |
518 } | 552 } |
519 | 553 |
520 // Run on I/O thread | 554 // Run on I/O thread |
521 void DevToolsHttpHandlerImpl::TeardownAndRelease() { | 555 void DevToolsHttpHandlerImpl::TeardownAndRelease() { |
522 server_ = NULL; | 556 server_ = NULL; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
582 | 616 |
583 void DevToolsHttpHandlerImpl::AcceptWebSocket( | 617 void DevToolsHttpHandlerImpl::AcceptWebSocket( |
584 int connection_id, | 618 int connection_id, |
585 const net::HttpServerRequestInfo& request) { | 619 const net::HttpServerRequestInfo& request) { |
586 BrowserThread::PostTask( | 620 BrowserThread::PostTask( |
587 BrowserThread::IO, FROM_HERE, | 621 BrowserThread::IO, FROM_HERE, |
588 base::Bind(&net::HttpServer::AcceptWebSocket, server_.get(), | 622 base::Bind(&net::HttpServer::AcceptWebSocket, server_.get(), |
589 connection_id, request)); | 623 connection_id, request)); |
590 } | 624 } |
591 | 625 |
592 size_t DevToolsHttpHandlerImpl::BindRenderViewHost(RenderViewHost* rvh) { | |
593 Target target = std::make_pair(rvh->GetProcess()->GetID(), | |
594 rvh->GetRoutingID()); | |
595 targets_.push_back(target); | |
596 return targets_.size() - 1; | |
597 } | |
598 | |
599 RenderViewHost* DevToolsHttpHandlerImpl::GetBoundRenderViewHost(size_t id) { | |
600 return RenderViewHost::FromID(targets_[id].first, | |
601 targets_[id].second); | |
602 } | |
603 | |
604 void DevToolsHttpHandlerImpl::ResetRenderViewHostBinding() { | |
605 targets_.clear(); | |
606 } | |
607 | |
608 } // namespace content | 626 } // namespace content |
OLD | NEW |