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

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

Issue 12319114: Extract debugger target enumeration into a separate class (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@debugger
Patch Set: Cleaner version ready for review Created 7 years, 9 months 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" 5 #include "content/browser/devtools/devtools_http_handler_impl.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/compiler_specific.h" 11 #include "base/compiler_specific.h"
12 #include "base/file_util.h" 12 #include "base/file_util.h"
13 #include "base/json/json_writer.h" 13 #include "base/json/json_writer.h"
14 #include "base/lazy_instance.h" 14 #include "base/lazy_instance.h"
15 #include "base/logging.h" 15 #include "base/logging.h"
16 #include "base/message_loop_proxy.h" 16 #include "base/message_loop_proxy.h"
17 #include "base/string_number_conversions.h" 17 #include "base/string_number_conversions.h"
18 #include "base/stringprintf.h"
19 #include "base/threading/thread.h" 18 #include "base/threading/thread.h"
20 #include "base/utf_string_conversions.h"
21 #include "base/values.h"
22 #include "content/browser/devtools/devtools_agent_host_impl.h"
23 #include "content/browser/devtools/devtools_browser_target.h" 19 #include "content/browser/devtools/devtools_browser_target.h"
24 #include "content/browser/devtools/devtools_tracing_handler.h" 20 #include "content/browser/devtools/devtools_tracing_handler.h"
25 #include "content/browser/web_contents/web_contents_impl.h" 21 #include "content/browser/web_contents/web_contents_impl.h"
26 #include "content/common/devtools_messages.h" 22 #include "content/common/devtools_messages.h"
27 #include "content/public/browser/browser_thread.h" 23 #include "content/public/browser/browser_thread.h"
28 #include "content/public/browser/devtools_agent_host.h" 24 #include "content/public/browser/devtools_agent_host.h"
29 #include "content/public/browser/devtools_client_host.h" 25 #include "content/public/browser/devtools_client_host.h"
30 #include "content/public/browser/devtools_http_handler_delegate.h"
31 #include "content/public/browser/devtools_manager.h" 26 #include "content/public/browser/devtools_manager.h"
32 #include "content/public/browser/favicon_status.h" 27 #include "content/public/browser/devtools_target_list.h"
33 #include "content/public/browser/navigation_entry.h"
34 #include "content/public/browser/notification_service.h" 28 #include "content/public/browser/notification_service.h"
35 #include "content/public/browser/notification_types.h" 29 #include "content/public/browser/notification_types.h"
36 #include "content/public/browser/render_process_host.h"
37 #include "content/public/browser/render_view_host.h" 30 #include "content/public/browser/render_view_host.h"
38 #include "content/public/browser/render_widget_host.h"
39 #include "content/public/common/content_client.h" 31 #include "content/public/common/content_client.h"
40 #include "content/public/common/url_constants.h" 32 #include "content/public/common/url_constants.h"
41 #include "googleurl/src/gurl.h" 33 #include "googleurl/src/gurl.h"
42 #include "grit/devtools_resources_map.h" 34 #include "grit/devtools_resources_map.h"
43 #include "net/base/escape.h"
44 #include "net/base/io_buffer.h" 35 #include "net/base/io_buffer.h"
45 #include "net/base/ip_endpoint.h" 36 #include "net/base/ip_endpoint.h"
46 #include "net/server/http_server_request_info.h" 37 #include "net/server/http_server_request_info.h"
47 #include "third_party/WebKit/Source/Platform/chromium/public/WebString.h" 38 #include "third_party/WebKit/Source/Platform/chromium/public/WebString.h"
48 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDevToolsAgent.h" 39 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDevToolsAgent.h"
49 #include "ui/base/layout.h" 40 #include "ui/base/layout.h"
50 #include "webkit/user_agent/user_agent.h" 41 #include "webkit/user_agent/user_agent.h"
51 #include "webkit/user_agent/user_agent_util.h" 42 #include "webkit/user_agent/user_agent_util.h"
52 43
53 namespace content { 44 namespace content {
54 45
55 const int kBufferSize = 16 * 1024; 46 const int kBufferSize = 16 * 1024;
56 47
57 namespace { 48 namespace {
58 49
59 static const char* kDevToolsHandlerThreadName = "Chrome_DevToolsHandlerThread"; 50 static const char* kDevToolsHandlerThreadName = "Chrome_DevToolsHandlerThread";
60 51
61 class DevToolsDefaultBindingHandler
62 : public DevToolsHttpHandler::DevToolsAgentHostBinding {
63 public:
64 DevToolsDefaultBindingHandler() {
65 }
66
67 void GarbageCollect() {
68 AgentsMap::iterator it = agents_map_.begin();
69 while (it != agents_map_.end()) {
70 if (!it->second->GetRenderViewHost())
71 agents_map_.erase(it++);
72 else
73 ++it;
74 }
75 }
76
77 virtual std::string GetIdentifier(DevToolsAgentHost* agent_host) OVERRIDE {
78 GarbageCollect();
79 DevToolsAgentHostImpl* agent_host_impl =
80 static_cast<DevToolsAgentHostImpl*>(agent_host);
81 std::string id = base::StringPrintf("%d", agent_host_impl->id());
82 agents_map_[id] = agent_host;
83 return id;
84 }
85
86 virtual DevToolsAgentHost* ForIdentifier(
87 const std::string& identifier) OVERRIDE {
88 GarbageCollect();
89 AgentsMap::iterator it = agents_map_.find(identifier);
90 if (it != agents_map_.end())
91 return it->second;
92 return NULL;
93 }
94
95 private:
96 typedef std::map<std::string, scoped_refptr<DevToolsAgentHost> > AgentsMap;
97 AgentsMap agents_map_;
98 };
99
100 // An internal implementation of DevToolsClientHost that delegates 52 // An internal implementation of DevToolsClientHost that delegates
101 // messages sent for DevToolsClient to a DebuggerShell instance. 53 // messages sent for DevToolsClient to a DebuggerShell instance.
102 class DevToolsClientHostImpl : public DevToolsClientHost { 54 class DevToolsClientHostImpl : public DevToolsClientHost {
103 public: 55 public:
104 DevToolsClientHostImpl( 56 DevToolsClientHostImpl(
105 MessageLoop* message_loop, 57 MessageLoop* message_loop,
106 net::HttpServer* server, 58 net::HttpServer* server,
107 int connection_id) 59 int connection_id)
108 : message_loop_(message_loop), 60 : message_loop_(message_loop),
109 server_(server), 61 server_(server),
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 BrowserThread::FILE, FROM_HERE, 180 BrowserThread::FILE, FROM_HERE,
229 base::Bind(&DevToolsHttpHandlerImpl::StopHandlerThread, this), 181 base::Bind(&DevToolsHttpHandlerImpl::StopHandlerThread, this),
230 base::Bind(&DevToolsHttpHandlerImpl::ResetHandlerThreadAndRelease, this)); 182 base::Bind(&DevToolsHttpHandlerImpl::ResetHandlerThreadAndRelease, this));
231 } 183 }
232 184
233 void DevToolsHttpHandlerImpl::SetDevToolsAgentHostBinding( 185 void DevToolsHttpHandlerImpl::SetDevToolsAgentHostBinding(
234 DevToolsAgentHostBinding* binding) { 186 DevToolsAgentHostBinding* binding) {
235 if (binding) 187 if (binding)
236 binding_ = binding; 188 binding_ = binding;
237 else 189 else
238 binding_ = default_binding_.get(); 190 binding_ = DevToolsTargetList::GetInstance();
pfeldman 2013/03/01 08:49:30 It is especially clear here how two concepts are m
Vladislav Kaznacheev 2013/03/01 12:58:35 Rolled back. On 2013/03/01 08:49:30, pfeldman wrot
239 } 191 }
240 192
241 GURL DevToolsHttpHandlerImpl::GetFrontendURL(DevToolsAgentHost* agent_host) { 193 GURL DevToolsHttpHandlerImpl::GetFrontendURL(DevToolsAgentHost* agent_host) {
242 net::IPEndPoint ip_address; 194 net::IPEndPoint ip_address;
243 if (server_->GetLocalAddress(&ip_address)) 195 if (server_->GetLocalAddress(&ip_address))
244 return GURL(); 196 return GURL();
245 if (!agent_host) { 197 if (!agent_host) {
246 return GURL(std::string("http://") + ip_address.ToString() + 198 return GURL(std::string("http://") + ip_address.ToString() +
247 overridden_frontend_url_); 199 overridden_frontend_url_);
248 } 200 }
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 void DevToolsHttpHandlerImpl::OnClose(int connection_id) { 339 void DevToolsHttpHandlerImpl::OnClose(int connection_id) {
388 BrowserThread::PostTask( 340 BrowserThread::PostTask(
389 BrowserThread::UI, 341 BrowserThread::UI,
390 FROM_HERE, 342 FROM_HERE,
391 base::Bind( 343 base::Bind(
392 &DevToolsHttpHandlerImpl::OnCloseUI, 344 &DevToolsHttpHandlerImpl::OnCloseUI,
393 this, 345 this,
394 connection_id)); 346 connection_id));
395 } 347 }
396 348
397 struct DevToolsHttpHandlerImpl::PageInfo { 349 static base::TimeTicks GetLastSelectedTime(DevToolsAgentHost* agent) {
398 PageInfo() 350 WebContents* web_contents =
pfeldman 2013/03/01 08:49:30 Once you start operating TargetList, some of your
Vladislav Kaznacheev 2013/03/01 12:58:35 This will not solve the problem from your next com
399 : attached(false) { 351 agent->GetRenderViewHost()->GetDelegate()->GetAsWebContents();
400 } 352 return web_contents ? web_contents->GetLastSelectedTime() : base::TimeTicks();
401 353 }
402 std::string id;
403 std::string url;
404 std::string type;
405 bool attached;
406 std::string title;
407 std::string thumbnail_url;
408 std::string favicon_url;
409 base::TimeTicks last_selected_time;
410 };
411 354
412 // static 355 // static
413 bool DevToolsHttpHandlerImpl::SortPageListByTime(const PageInfo& info1, 356 bool DevToolsHttpHandlerImpl::SortPageListByTime(DevToolsAgentHost* agent1,
414 const PageInfo& info2) { 357 DevToolsAgentHost* agent2) {
415 return info1.last_selected_time > info2.last_selected_time; 358 return GetLastSelectedTime(agent1) > GetLastSelectedTime(agent2);
pfeldman 2013/03/01 08:49:30 This is scary. GetLastSelectedTime will return dif
Vladislav Kaznacheev 2013/03/01 12:58:35 I am scared too. On 2013/03/01 08:49:30, pfeldman
416 } 359 }
417 360
418 DevToolsHttpHandlerImpl::PageList DevToolsHttpHandlerImpl::GeneratePageList() { 361 DevToolsHttpHandlerImpl::PageList DevToolsHttpHandlerImpl::GeneratePageList() {
419 PageList page_list; 362 PageList page_list;
420 for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator()); 363 DevToolsTargetList::AgentsMap& agents_map =
421 !it.IsAtEnd(); it.Advance()) { 364 DevToolsTargetList::GetInstance()->GetAgentsMap();
422 RenderProcessHost* render_process_host = it.GetCurrentValue(); 365 for (DevToolsTargetList::iterator i = agents_map.begin();
423 DCHECK(render_process_host); 366 i != agents_map.end(); ++i)
424 367 page_list.push_back(i->second);
425 // Ignore processes that don't have a connection, such as crashed contents.
426 if (!render_process_host->HasConnection())
427 continue;
428
429 RenderProcessHost::RenderWidgetHostsIterator rwit(
430 render_process_host->GetRenderWidgetHostsIterator());
431 for (; !rwit.IsAtEnd(); rwit.Advance()) {
432 const RenderWidgetHost* widget = rwit.GetCurrentValue();
433 DCHECK(widget);
434 if (!widget || !widget->IsRenderView())
435 continue;
436
437 RenderViewHost* host =
438 RenderViewHost::From(const_cast<RenderWidgetHost*>(widget));
439 page_list.push_back(CreatePageInfo(host, delegate_->GetTargetType(host)));
440 }
441 }
442 std::sort(page_list.begin(), page_list.end(), SortPageListByTime); 368 std::sort(page_list.begin(), page_list.end(), SortPageListByTime);
443 return page_list; 369 return page_list;
444 } 370 }
445 371
446 std::string DevToolsHttpHandlerImpl::GetFrontendURLInternal( 372 std::string DevToolsHttpHandlerImpl::GetFrontendURLInternal(
447 const std::string rvh_id, 373 const std::string rvh_id,
448 const std::string& host) { 374 const std::string& host) {
449 return base::StringPrintf( 375 return base::StringPrintf(
450 "%s%sws=%s/devtools/page/%s", 376 "%s%sws=%s/devtools/page/%s",
451 overridden_frontend_url_.c_str(), 377 overridden_frontend_url_.c_str(),
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
538 if (command == "new") { 464 if (command == "new") {
539 RenderViewHost* rvh = delegate_->CreateNewTarget(); 465 RenderViewHost* rvh = delegate_->CreateNewTarget();
540 if (!rvh) { 466 if (!rvh) {
541 SendJson(connection_id, 467 SendJson(connection_id,
542 net::HTTP_INTERNAL_SERVER_ERROR, 468 net::HTTP_INTERNAL_SERVER_ERROR,
543 NULL, 469 NULL,
544 "Could not create new page", 470 "Could not create new page",
545 jsonp); 471 jsonp);
546 return; 472 return;
547 } 473 }
548 PageInfo page_info =
549 CreatePageInfo(rvh, DevToolsHttpHandlerDelegate::kTargetTypeTab);
550 std::string host = info.headers["Host"]; 474 std::string host = info.headers["Host"];
551 scoped_ptr<base::DictionaryValue> dictionary( 475 scoped_ptr<base::DictionaryValue> dictionary(
552 SerializePageInfo(page_info, host)); 476 SerializePageInfo(DevToolsAgentHost::GetFor(rvh), host));
553 SendJson(connection_id, net::HTTP_OK, dictionary.get(), "", jsonp); 477 SendJson(connection_id, net::HTTP_OK, dictionary.get(), "", jsonp);
554 return; 478 return;
555 } 479 }
556 480
557 if (command == "activate" || command == "close") { 481 if (command == "activate" || command == "close") {
558 DevToolsAgentHost* agent_host = binding_->ForIdentifier(target_id); 482 DevToolsAgentHost* agent_host = binding_->ForIdentifier(target_id);
559 RenderViewHost* rvh = agent_host ? agent_host->GetRenderViewHost() : NULL; 483 RenderViewHost* rvh = agent_host ? agent_host->GetRenderViewHost() : NULL;
560 if (!rvh) { 484 if (!rvh) {
561 SendJson(connection_id, 485 SendJson(connection_id,
562 net::HTTP_NOT_FOUND, 486 net::HTTP_NOT_FOUND,
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
706 DevToolsHttpHandlerImpl::DevToolsHttpHandlerImpl( 630 DevToolsHttpHandlerImpl::DevToolsHttpHandlerImpl(
707 const net::StreamListenSocketFactory* socket_factory, 631 const net::StreamListenSocketFactory* socket_factory,
708 const std::string& frontend_url, 632 const std::string& frontend_url,
709 DevToolsHttpHandlerDelegate* delegate) 633 DevToolsHttpHandlerDelegate* delegate)
710 : overridden_frontend_url_(frontend_url), 634 : overridden_frontend_url_(frontend_url),
711 socket_factory_(socket_factory), 635 socket_factory_(socket_factory),
712 delegate_(delegate) { 636 delegate_(delegate) {
713 if (overridden_frontend_url_.empty()) 637 if (overridden_frontend_url_.empty())
714 overridden_frontend_url_ = "/devtools/devtools.html"; 638 overridden_frontend_url_ = "/devtools/devtools.html";
715 639
716 default_binding_.reset(new DevToolsDefaultBindingHandler); 640 binding_ = DevToolsTargetList::GetInstance();
717 binding_ = default_binding_.get();
718 641
719 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_TERMINATED, 642 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_TERMINATED,
720 NotificationService::AllBrowserContextsAndSources()); 643 NotificationService::AllBrowserContextsAndSources());
721 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_CLOSED, 644 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_CLOSED,
722 NotificationService::AllBrowserContextsAndSources()); 645 NotificationService::AllBrowserContextsAndSources());
723 646
724 // Balanced in ResetHandlerThreadAndRelease(). 647 // Balanced in ResetHandlerThreadAndRelease().
725 AddRef(); 648 AddRef();
726 } 649 }
727 650
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
830 int connection_id, 753 int connection_id,
831 const net::HttpServerRequestInfo& request) { 754 const net::HttpServerRequestInfo& request) {
832 if (!thread_.get()) 755 if (!thread_.get())
833 return; 756 return;
834 thread_->message_loop()->PostTask( 757 thread_->message_loop()->PostTask(
835 FROM_HERE, 758 FROM_HERE,
836 base::Bind(&net::HttpServer::AcceptWebSocket, server_.get(), 759 base::Bind(&net::HttpServer::AcceptWebSocket, server_.get(),
837 connection_id, request)); 760 connection_id, request));
838 } 761 }
839 762
840 DevToolsHttpHandlerImpl::PageInfo 763 base::DictionaryValue* DevToolsHttpHandlerImpl::SerializePageInfo(
841 DevToolsHttpHandlerImpl::CreatePageInfo(RenderViewHost* rvh, 764 DevToolsAgentHost* agent_host,
842 DevToolsHttpHandlerDelegate::TargetType type) { 765 const std::string& host) {
843 RenderViewHostDelegate* host_delegate = rvh->GetDelegate(); 766 base::DictionaryValue* dictionary = new base::DictionaryValue;
844 scoped_refptr<DevToolsAgentHost> agent(DevToolsAgentHost::GetFor(rvh)); 767 dictionary->SetString("title", agent_host->title());
845 DevToolsClientHost* client_host = DevToolsManager::GetInstance()-> 768 dictionary->SetString("url", agent_host->url().spec());
846 GetDevToolsClientHostFor(agent); 769 switch (delegate_->GetTargetType(agent_host->GetRenderViewHost())) {
847 PageInfo page_info;
848 page_info.id = binding_->GetIdentifier(agent);
849 page_info.attached = client_host != NULL;
850 page_info.url = host_delegate->GetURL().spec();
851
852 switch (type) {
853 case DevToolsHttpHandlerDelegate::kTargetTypeTab: 770 case DevToolsHttpHandlerDelegate::kTargetTypeTab:
854 page_info.type = "page"; 771 dictionary->SetString("type", "page");
855 break; 772 break;
856 default: 773 default:
857 page_info.type = "other"; 774 dictionary->SetString("type", "other");
858 } 775 }
859 776 std::string id = binding_->GetIdentifier(agent_host);
860 WebContents* web_contents = host_delegate->GetAsWebContents(); 777 dictionary->SetString("id", id);
861 if (web_contents) { 778 dictionary->SetString("thumbnailUrl", agent_host->thumbnail_url().spec());
862 page_info.title = UTF16ToUTF8( 779 dictionary->SetString("faviconUrl", agent_host->favicon_url().spec());
863 net::EscapeForHTML(web_contents->GetTitle())); 780 if (!agent_host->attached()) {
864 page_info.last_selected_time = web_contents->GetLastSelectedTime();
865
866 NavigationController& controller = web_contents->GetController();
867 NavigationEntry* entry = controller.GetActiveEntry();
868 if (entry != NULL && entry->GetURL().is_valid()) {
869 page_info.thumbnail_url = "/thumb/" + entry->GetURL().spec();
870 page_info.favicon_url = entry->GetFavicon().url.spec();
871 }
872 }
873 return page_info;
874 }
875
876 base::DictionaryValue* DevToolsHttpHandlerImpl::SerializePageInfo(
877 const PageInfo& page_info,
878 const std::string& host) {
879 base::DictionaryValue* dictionary = new base::DictionaryValue;
880 dictionary->SetString("title", page_info.title);
881 dictionary->SetString("url", page_info.url);
882 dictionary->SetString("type", page_info.type);
883 dictionary->SetString("id", page_info.id);
884 dictionary->SetString("thumbnailUrl", page_info.thumbnail_url);
885 dictionary->SetString("faviconUrl", page_info.favicon_url);
886 if (!page_info.attached) {
887 dictionary->SetString("webSocketDebuggerUrl", 781 dictionary->SetString("webSocketDebuggerUrl",
888 base::StringPrintf("ws://%s/devtools/page/%s", 782 base::StringPrintf("ws://%s/devtools/page/%s",
889 host.c_str(), 783 host.c_str(),
890 page_info.id.c_str())); 784 id.c_str()));
891 std::string devtools_frontend_url = GetFrontendURLInternal( 785 std::string devtools_frontend_url = GetFrontendURLInternal(
892 page_info.id.c_str(), 786 id.c_str(),
893 host); 787 host);
894 dictionary->SetString("devtoolsFrontendUrl", devtools_frontend_url); 788 dictionary->SetString("devtoolsFrontendUrl", devtools_frontend_url);
895 } 789 }
896 return dictionary; 790 return dictionary;
897 } 791 }
898 792
899 } // namespace content 793 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698