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

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: Addressed comments 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"
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 #include "webkit/user_agent/user_agent_util.h" 51 #include "webkit/user_agent/user_agent_util.h"
52 52
53 namespace content { 53 namespace content {
54 54
55 const int kBufferSize = 16 * 1024; 55 const int kBufferSize = 16 * 1024;
56 56
57 namespace { 57 namespace {
58 58
59 static const char* kDevToolsHandlerThreadName = "Chrome_DevToolsHandlerThread"; 59 static const char* kDevToolsHandlerThreadName = "Chrome_DevToolsHandlerThread";
60 60
61 static const char* kThumbUrlPrefix = "/thumb/";
62
61 class DevToolsDefaultBindingHandler 63 class DevToolsDefaultBindingHandler
62 : public DevToolsHttpHandler::DevToolsAgentHostBinding { 64 : public DevToolsHttpHandler::DevToolsAgentHostBinding {
63 public: 65 public:
64 DevToolsDefaultBindingHandler() { 66 DevToolsDefaultBindingHandler() {
65 } 67 }
66 68
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 { 69 virtual std::string GetIdentifier(DevToolsAgentHost* agent_host) OVERRIDE {
78 GarbageCollect(); 70 return agent_host->GetId();
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 } 71 }
85 72
86 virtual DevToolsAgentHost* ForIdentifier( 73 virtual DevToolsAgentHost* ForIdentifier(
87 const std::string& identifier) OVERRIDE { 74 const std::string& identifier) OVERRIDE {
88 GarbageCollect(); 75 return DevToolsAgentHost::GetRetained(identifier);
89 AgentsMap::iterator it = agents_map_.find(identifier);
90 if (it != agents_map_.end())
91 return it->second;
92 return NULL;
93 } 76 }
94
95 private:
96 typedef std::map<std::string, scoped_refptr<DevToolsAgentHost> > AgentsMap;
97 AgentsMap agents_map_;
98 }; 77 };
99 78
100 // An internal implementation of DevToolsClientHost that delegates 79 // An internal implementation of DevToolsClientHost that delegates
101 // messages sent for DevToolsClient to a DebuggerShell instance. 80 // messages sent for DevToolsClient to a DebuggerShell instance.
102 class DevToolsClientHostImpl : public DevToolsClientHost { 81 class DevToolsClientHostImpl : public DevToolsClientHost {
103 public: 82 public:
104 DevToolsClientHostImpl( 83 DevToolsClientHostImpl(
105 MessageLoop* message_loop, 84 MessageLoop* message_loop,
106 net::HttpServer* server, 85 net::HttpServer* server,
107 int connection_id) 86 int connection_id)
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 } 128 }
150 129
151 private: 130 private:
152 MessageLoop* message_loop_; 131 MessageLoop* message_loop_;
153 net::HttpServer* server_; 132 net::HttpServer* server_;
154 int connection_id_; 133 int connection_id_;
155 bool is_closed_; 134 bool is_closed_;
156 std::string detach_reason_; 135 std::string detach_reason_;
157 }; 136 };
158 137
138 static base::TimeTicks GetLastSelectedTime(RenderViewHost* rvh) {
139 WebContents* web_contents = rvh->GetDelegate()->GetAsWebContents();
140 if (!web_contents)
141 return base::TimeTicks();
142
143 return web_contents->GetLastSelectedTime();
144 }
145
146 typedef std::pair<RenderViewHost*, base::TimeTicks> PageInfo;
147
148 static bool TimeComparator(const PageInfo& info1, const PageInfo& info2) {
149 return info1.second > info2.second;
150 }
151
159 } // namespace 152 } // namespace
160 153
161 // static 154 // static
162 int DevToolsHttpHandler::GetFrontendResourceId(const std::string& name) { 155 int DevToolsHttpHandler::GetFrontendResourceId(const std::string& name) {
163 for (size_t i = 0; i < kDevtoolsResourcesSize; ++i) { 156 for (size_t i = 0; i < kDevtoolsResourcesSize; ++i) {
164 if (name == kDevtoolsResources[i].name) 157 if (name == kDevtoolsResources[i].name)
165 return kDevtoolsResources[i].value; 158 return kDevtoolsResources[i].value;
166 } 159 }
167 return -1; 160 return -1;
168 } 161 }
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
300 BrowserThread::PostTask( 293 BrowserThread::PostTask(
301 BrowserThread::UI, 294 BrowserThread::UI,
302 FROM_HERE, 295 FROM_HERE,
303 base::Bind(&DevToolsHttpHandlerImpl::OnJsonRequestUI, 296 base::Bind(&DevToolsHttpHandlerImpl::OnJsonRequestUI,
304 this, 297 this,
305 connection_id, 298 connection_id,
306 info)); 299 info));
307 return; 300 return;
308 } 301 }
309 302
310 if (info.path.find("/thumb/") == 0) { 303 if (info.path.find(kThumbUrlPrefix) == 0) {
311 // Thumbnail request. 304 // Thumbnail request.
305 const std::string target_id = info.path.substr(strlen(kThumbUrlPrefix));
306 DevToolsAgentHost* agent_host = binding_->ForIdentifier(target_id);
307 GURL page_url;
308 if (agent_host) {
309 RenderViewHost* rvh = agent_host->GetRenderViewHost();
310 if (rvh)
311 page_url = rvh->GetDelegate()->GetURL();
312 }
312 BrowserThread::PostTask( 313 BrowserThread::PostTask(
313 BrowserThread::UI, 314 BrowserThread::UI,
314 FROM_HERE, 315 FROM_HERE,
315 base::Bind(&DevToolsHttpHandlerImpl::OnThumbnailRequestUI, 316 base::Bind(&DevToolsHttpHandlerImpl::OnThumbnailRequestUI,
316 this, 317 this,
317 connection_id, 318 connection_id,
318 info)); 319 page_url));
319 return; 320 return;
320 } 321 }
321 322
322 if (info.path == "" || info.path == "/") { 323 if (info.path == "" || info.path == "/") {
323 // Discovery page request. 324 // Discovery page request.
324 BrowserThread::PostTask( 325 BrowserThread::PostTask(
325 BrowserThread::UI, 326 BrowserThread::UI,
326 FROM_HERE, 327 FROM_HERE,
327 base::Bind(&DevToolsHttpHandlerImpl::OnDiscoveryPageRequestUI, 328 base::Bind(&DevToolsHttpHandlerImpl::OnDiscoveryPageRequestUI,
328 this, 329 this,
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 void DevToolsHttpHandlerImpl::OnClose(int connection_id) { 388 void DevToolsHttpHandlerImpl::OnClose(int connection_id) {
388 BrowserThread::PostTask( 389 BrowserThread::PostTask(
389 BrowserThread::UI, 390 BrowserThread::UI,
390 FROM_HERE, 391 FROM_HERE,
391 base::Bind( 392 base::Bind(
392 &DevToolsHttpHandlerImpl::OnCloseUI, 393 &DevToolsHttpHandlerImpl::OnCloseUI,
393 this, 394 this,
394 connection_id)); 395 connection_id));
395 } 396 }
396 397
397 struct DevToolsHttpHandlerImpl::PageInfo {
398 PageInfo()
399 : attached(false) {
400 }
401
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
412 // static
413 bool DevToolsHttpHandlerImpl::SortPageListByTime(const PageInfo& info1,
414 const PageInfo& info2) {
415 return info1.last_selected_time > info2.last_selected_time;
416 }
417
418 DevToolsHttpHandlerImpl::PageList DevToolsHttpHandlerImpl::GeneratePageList() {
419 PageList page_list;
420 for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
421 !it.IsAtEnd(); it.Advance()) {
422 RenderProcessHost* render_process_host = it.GetCurrentValue();
423 DCHECK(render_process_host);
424
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);
443 return page_list;
444 }
445
446 std::string DevToolsHttpHandlerImpl::GetFrontendURLInternal( 398 std::string DevToolsHttpHandlerImpl::GetFrontendURLInternal(
447 const std::string rvh_id, 399 const std::string rvh_id,
448 const std::string& host) { 400 const std::string& host) {
449 return base::StringPrintf( 401 return base::StringPrintf(
450 "%s%sws=%s/devtools/page/%s", 402 "%s%sws=%s/devtools/page/%s",
451 overridden_frontend_url_.c_str(), 403 overridden_frontend_url_.c_str(),
452 overridden_frontend_url_.find("?") == std::string::npos ? "?" : "&", 404 overridden_frontend_url_.find("?") == std::string::npos ? "?" : "&",
453 host.c_str(), 405 host.c_str(),
454 rvh_id.c_str()); 406 rvh_id.c_str());
455 } 407 }
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
519 webkit_glue::GetWebKitVersion()); 471 webkit_glue::GetWebKitVersion());
520 version.SetString("Browser", 472 version.SetString("Browser",
521 content::GetContentClient()->GetProduct()); 473 content::GetContentClient()->GetProduct());
522 version.SetString("User-Agent", 474 version.SetString("User-Agent",
523 webkit_glue::GetUserAgent(GURL(chrome::kAboutBlankURL))); 475 webkit_glue::GetUserAgent(GURL(chrome::kAboutBlankURL)));
524 SendJson(connection_id, net::HTTP_OK, &version, "", jsonp); 476 SendJson(connection_id, net::HTTP_OK, &version, "", jsonp);
525 return; 477 return;
526 } 478 }
527 479
528 if (command == "list") { 480 if (command == "list") {
529 PageList page_list = GeneratePageList(); 481 typedef std::vector<PageInfo> PageList;
482 PageList page_list;
483
484 std::vector<RenderViewHost*> rvh_list =
485 DevToolsAgentHost::GetValidRenderViewHosts();
486 DevToolsAgentHost::RetainFor(rvh_list);
487
488 for (std::vector<RenderViewHost*>::iterator it = rvh_list.begin();
489 it != rvh_list.end(); ++it)
490 page_list.push_back(PageInfo(*it, GetLastSelectedTime(*it)));
491
492 std::sort(page_list.begin(), page_list.end(), TimeComparator);
493
530 base::ListValue json_pages_list; 494 base::ListValue json_pages_list;
531 std::string host = info.headers["Host"]; 495 std::string host = info.headers["Host"];
532 for (PageList::iterator i = page_list.begin(); i != page_list.end(); ++i) 496 for (PageList::iterator i = page_list.begin(); i != page_list.end(); ++i)
533 json_pages_list.Append(SerializePageInfo(*i, host)); 497 json_pages_list.Append(SerializePageInfo(i->first, host));
534 SendJson(connection_id, net::HTTP_OK, &json_pages_list, "", jsonp); 498 SendJson(connection_id, net::HTTP_OK, &json_pages_list, "", jsonp);
535 return; 499 return;
536 } 500 }
537 501
538 if (command == "new") { 502 if (command == "new") {
539 RenderViewHost* rvh = delegate_->CreateNewTarget(); 503 RenderViewHost* rvh = delegate_->CreateNewTarget();
540 if (!rvh) { 504 if (!rvh) {
541 SendJson(connection_id, 505 SendJson(connection_id,
542 net::HTTP_INTERNAL_SERVER_ERROR, 506 net::HTTP_INTERNAL_SERVER_ERROR,
543 NULL, 507 NULL,
544 "Could not create new page", 508 "Could not create new page",
545 jsonp); 509 jsonp);
546 return; 510 return;
547 } 511 }
548 PageInfo page_info =
549 CreatePageInfo(rvh, DevToolsHttpHandlerDelegate::kTargetTypeTab);
550 std::string host = info.headers["Host"]; 512 std::string host = info.headers["Host"];
551 scoped_ptr<base::DictionaryValue> dictionary( 513 std::vector<RenderViewHost*> rvh_list;
552 SerializePageInfo(page_info, host)); 514 rvh_list.push_back(rvh);
515 DevToolsAgentHost::RetainFor(rvh_list);
516 scoped_ptr<base::DictionaryValue> dictionary(SerializePageInfo(rvh, host));
553 SendJson(connection_id, net::HTTP_OK, dictionary.get(), "", jsonp); 517 SendJson(connection_id, net::HTTP_OK, dictionary.get(), "", jsonp);
554 return; 518 return;
555 } 519 }
556 520
557 if (command == "activate" || command == "close") { 521 if (command == "activate" || command == "close") {
558 DevToolsAgentHost* agent_host = binding_->ForIdentifier(target_id); 522 DevToolsAgentHost* agent_host = binding_->ForIdentifier(target_id);
559 RenderViewHost* rvh = agent_host ? agent_host->GetRenderViewHost() : NULL; 523 RenderViewHost* rvh = agent_host ? agent_host->GetRenderViewHost() : NULL;
560 if (!rvh) { 524 if (!rvh) {
561 SendJson(connection_id, 525 SendJson(connection_id,
562 net::HTTP_NOT_FOUND, 526 net::HTTP_NOT_FOUND,
(...skipping 17 matching lines...) Expand all
580 } 544 }
581 SendJson(connection_id, 545 SendJson(connection_id,
582 net::HTTP_NOT_FOUND, 546 net::HTTP_NOT_FOUND,
583 NULL, 547 NULL,
584 "Unknown command: " + command, 548 "Unknown command: " + command,
585 jsonp); 549 jsonp);
586 return; 550 return;
587 } 551 }
588 552
589 void DevToolsHttpHandlerImpl::OnThumbnailRequestUI( 553 void DevToolsHttpHandlerImpl::OnThumbnailRequestUI(
590 int connection_id, 554 int connection_id, const GURL& page_url) {
591 const net::HttpServerRequestInfo& info) { 555 std::string data = delegate_->GetPageThumbnailData(page_url);
592 std::string prefix = "/thumb/";
593 size_t pos = info.path.find(prefix);
594 if (pos != 0) {
595 Send404(connection_id);
596 return;
597 }
598
599 std::string page_url = info.path.substr(prefix.length());
600 std::string data = delegate_->GetPageThumbnailData(GURL(page_url));
601 if (!data.empty()) 556 if (!data.empty())
602 Send200(connection_id, data, "image/png"); 557 Send200(connection_id, data, "image/png");
603 else 558 else
604 Send404(connection_id); 559 Send404(connection_id);
605 } 560 }
606 561
607 void DevToolsHttpHandlerImpl::OnDiscoveryPageRequestUI(int connection_id) { 562 void DevToolsHttpHandlerImpl::OnDiscoveryPageRequestUI(int connection_id) {
608 std::string response = delegate_->GetDiscoveryPageHTML(); 563 std::string response = delegate_->GetDiscoveryPageHTML();
609 Send200(connection_id, response, "text/html; charset=UTF-8"); 564 Send200(connection_id, response, "text/html; charset=UTF-8");
610 } 565 }
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
830 int connection_id, 785 int connection_id,
831 const net::HttpServerRequestInfo& request) { 786 const net::HttpServerRequestInfo& request) {
832 if (!thread_.get()) 787 if (!thread_.get())
833 return; 788 return;
834 thread_->message_loop()->PostTask( 789 thread_->message_loop()->PostTask(
835 FROM_HERE, 790 FROM_HERE,
836 base::Bind(&net::HttpServer::AcceptWebSocket, server_.get(), 791 base::Bind(&net::HttpServer::AcceptWebSocket, server_.get(),
837 connection_id, request)); 792 connection_id, request));
838 } 793 }
839 794
840 DevToolsHttpHandlerImpl::PageInfo 795 base::DictionaryValue* DevToolsHttpHandlerImpl::SerializePageInfo(
841 DevToolsHttpHandlerImpl::CreatePageInfo(RenderViewHost* rvh, 796 RenderViewHost* rvh,
842 DevToolsHttpHandlerDelegate::TargetType type) { 797 const std::string& host) {
843 RenderViewHostDelegate* host_delegate = rvh->GetDelegate(); 798 base::DictionaryValue* dictionary = new base::DictionaryValue;
799
844 scoped_refptr<DevToolsAgentHost> agent(DevToolsAgentHost::GetFor(rvh)); 800 scoped_refptr<DevToolsAgentHost> agent(DevToolsAgentHost::GetFor(rvh));
845 DevToolsClientHost* client_host = DevToolsManager::GetInstance()->
846 GetDevToolsClientHostFor(agent);
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 801
852 switch (type) { 802 std::string id = binding_->GetIdentifier(agent);
803 dictionary->SetString("id", id);
804
805 switch (delegate_->GetTargetType(rvh)) {
853 case DevToolsHttpHandlerDelegate::kTargetTypeTab: 806 case DevToolsHttpHandlerDelegate::kTargetTypeTab:
854 page_info.type = "page"; 807 dictionary->SetString("type", "page");
855 break; 808 break;
856 default: 809 default:
857 page_info.type = "other"; 810 dictionary->SetString("type", "other");
858 } 811 }
859 812
860 WebContents* web_contents = host_delegate->GetAsWebContents(); 813 WebContents* web_contents = rvh->GetDelegate()->GetAsWebContents();
861 if (web_contents) { 814 if (web_contents) {
862 page_info.title = UTF16ToUTF8( 815 dictionary->SetString("title", UTF16ToUTF8(
863 net::EscapeForHTML(web_contents->GetTitle())); 816 net::EscapeForHTML(web_contents->GetTitle())));
864 page_info.last_selected_time = web_contents->GetLastSelectedTime(); 817 dictionary->SetString("url", web_contents->GetURL().spec());
818
819 dictionary->SetString("thumbnailUrl", std::string(kThumbUrlPrefix) + id);
865 820
866 NavigationController& controller = web_contents->GetController(); 821 NavigationController& controller = web_contents->GetController();
867 NavigationEntry* entry = controller.GetActiveEntry(); 822 NavigationEntry* entry = controller.GetActiveEntry();
868 if (entry != NULL && entry->GetURL().is_valid()) { 823 if (entry != NULL && entry->GetURL().is_valid()) {
869 page_info.thumbnail_url = "/thumb/" + entry->GetURL().spec(); 824 dictionary->SetString("faviconUrl", entry->GetFavicon().url.spec());
870 page_info.favicon_url = entry->GetFavicon().url.spec();
871 } 825 }
872 } 826 }
873 return page_info;
874 }
875 827
876 base::DictionaryValue* DevToolsHttpHandlerImpl::SerializePageInfo( 828 if (!DevToolsManager::GetInstance()->GetDevToolsClientHostFor(agent)) {
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", 829 dictionary->SetString("webSocketDebuggerUrl",
888 base::StringPrintf("ws://%s/devtools/page/%s", 830 base::StringPrintf("ws://%s/devtools/page/%s",
889 host.c_str(), 831 host.c_str(),
890 page_info.id.c_str())); 832 id.c_str()));
891 std::string devtools_frontend_url = GetFrontendURLInternal( 833 std::string devtools_frontend_url = GetFrontendURLInternal(
892 page_info.id.c_str(), 834 id.c_str(),
893 host); 835 host);
894 dictionary->SetString("devtoolsFrontendUrl", devtools_frontend_url); 836 dictionary->SetString("devtoolsFrontendUrl", devtools_frontend_url);
895 } 837 }
896 return dictionary; 838 return dictionary;
897 } 839 }
898 840
899 } // namespace content 841 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698