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/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 21 matching lines...) Expand all Loading... | |
32 #include "content/public/common/content_client.h" | 32 #include "content/public/common/content_client.h" |
33 #include "content/public/common/url_constants.h" | 33 #include "content/public/common/url_constants.h" |
34 #include "content/public/common/user_agent.h" | 34 #include "content/public/common/user_agent.h" |
35 #include "content/public/common/user_agent.h" | 35 #include "content/public/common/user_agent.h" |
36 #include "grit/devtools_resources_map.h" | 36 #include "grit/devtools_resources_map.h" |
37 #include "net/base/escape.h" | 37 #include "net/base/escape.h" |
38 #include "net/base/io_buffer.h" | 38 #include "net/base/io_buffer.h" |
39 #include "net/base/ip_endpoint.h" | 39 #include "net/base/ip_endpoint.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 | 43 |
43 #if defined(OS_ANDROID) | 44 #if defined(OS_ANDROID) |
44 #include "base/android/build_info.h" | 45 #include "base/android/build_info.h" |
45 #endif | 46 #endif |
46 | 47 |
47 namespace content { | 48 namespace content { |
48 | 49 |
49 namespace { | 50 namespace { |
50 | 51 |
51 const char kDevToolsHandlerThreadName[] = "Chrome_DevToolsHandlerThread"; | 52 const char kDevToolsHandlerThreadName[] = "Chrome_DevToolsHandlerThread"; |
52 | 53 |
53 const char kThumbUrlPrefix[] = "/thumb/"; | 54 const char kThumbUrlPrefix[] = "/thumb/"; |
54 const char kPageUrlPrefix[] = "/devtools/page/"; | 55 const char kPageUrlPrefix[] = "/devtools/page/"; |
55 | 56 |
56 const char kTargetIdField[] = "id"; | 57 const char kTargetIdField[] = "id"; |
57 const char kTargetTypeField[] = "type"; | 58 const char kTargetTypeField[] = "type"; |
58 const char kTargetTitleField[] = "title"; | 59 const char kTargetTitleField[] = "title"; |
59 const char kTargetDescriptionField[] = "description"; | 60 const char kTargetDescriptionField[] = "description"; |
60 const char kTargetUrlField[] = "url"; | 61 const char kTargetUrlField[] = "url"; |
61 const char kTargetThumbnailUrlField[] = "thumbnailUrl"; | 62 const char kTargetThumbnailUrlField[] = "thumbnailUrl"; |
62 const char kTargetFaviconUrlField[] = "faviconUrl"; | 63 const char kTargetFaviconUrlField[] = "faviconUrl"; |
63 const char kTargetWebSocketDebuggerUrlField[] = "webSocketDebuggerUrl"; | 64 const char kTargetWebSocketDebuggerUrlField[] = "webSocketDebuggerUrl"; |
64 const char kTargetDevtoolsFrontendUrlField[] = "devtoolsFrontendUrl"; | 65 const char kTargetDevtoolsFrontendUrlField[] = "devtoolsFrontendUrl"; |
65 | 66 |
66 // An internal implementation of DevToolsClientHost that delegates | 67 // An internal implementation of DevToolsClientHost that delegates |
67 // messages sent for DevToolsClient to a DebuggerShell instance. | 68 // messages sent for DevToolsClient to a DebuggerShell instance. |
68 class DevToolsClientHostImpl : public DevToolsClientHost { | 69 class DevToolsClientHostImpl : public DevToolsClientHost { |
69 public: | 70 public: |
70 DevToolsClientHostImpl(base::MessageLoop* message_loop, | 71 DevToolsClientHostImpl(base::MessageLoop* message_loop, |
71 net::HttpServer* server, | 72 base::WeakPtr<net::HttpServer> server, |
72 int connection_id) | 73 int connection_id) |
73 : message_loop_(message_loop), | 74 : message_loop_(message_loop), |
74 server_(server), | 75 server_(server), |
75 connection_id_(connection_id), | 76 connection_id_(connection_id), |
76 is_closed_(false), | 77 is_closed_(false), |
77 detach_reason_("target_closed") {} | 78 detach_reason_("target_closed") {} |
78 | 79 |
79 virtual ~DevToolsClientHostImpl() {} | 80 virtual ~DevToolsClientHostImpl() {} |
80 | 81 |
81 // DevToolsClientHost interface | 82 // DevToolsClientHost interface |
(...skipping 28 matching lines...) Expand all Loading... | |
110 connection_id_, | 111 connection_id_, |
111 data)); | 112 data)); |
112 } | 113 } |
113 | 114 |
114 virtual void ReplacedWithAnotherClient() OVERRIDE { | 115 virtual void ReplacedWithAnotherClient() OVERRIDE { |
115 detach_reason_ = "replaced_with_devtools"; | 116 detach_reason_ = "replaced_with_devtools"; |
116 } | 117 } |
117 | 118 |
118 private: | 119 private: |
119 base::MessageLoop* message_loop_; | 120 base::MessageLoop* message_loop_; |
120 net::HttpServer* server_; | 121 base::WeakPtr<net::HttpServer> server_; |
pfeldman
2014/05/22 06:01:05
It was not refcounting it, so you should be fine w
byungchul
2014/05/28 01:19:35
It is used in base::Bind() not to call when server
Ryan Sleevi
2014/05/28 01:36:26
Are you sure it's necessary? We may be able to get
byungchul
2014/05/30 00:19:02
It's challenging to make HttpServer callback-drive
| |
121 int connection_id_; | 122 int connection_id_; |
122 bool is_closed_; | 123 bool is_closed_; |
123 std::string detach_reason_; | 124 std::string detach_reason_; |
124 }; | 125 }; |
125 | 126 |
126 static bool TimeComparator(const DevToolsTarget* target1, | 127 static bool TimeComparator(const DevToolsTarget* target1, |
127 const DevToolsTarget* target2) { | 128 const DevToolsTarget* target2) { |
128 return target1->GetLastActivityTime() > target2->GetLastActivityTime(); | 129 return target1->GetLastActivityTime() > target2->GetLastActivityTime(); |
129 } | 130 } |
130 | 131 |
131 } // namespace | 132 } // namespace |
132 | 133 |
133 // static | 134 // static |
134 bool DevToolsHttpHandler::IsSupportedProtocolVersion( | 135 bool DevToolsHttpHandler::IsSupportedProtocolVersion( |
135 const std::string& version) { | 136 const std::string& version) { |
136 return devtools::IsSupportedProtocolVersion(version); | 137 return devtools::IsSupportedProtocolVersion(version); |
137 } | 138 } |
138 | 139 |
139 // static | 140 // static |
140 int DevToolsHttpHandler::GetFrontendResourceId(const std::string& name) { | 141 int DevToolsHttpHandler::GetFrontendResourceId(const std::string& name) { |
141 for (size_t i = 0; i < kDevtoolsResourcesSize; ++i) { | 142 for (size_t i = 0; i < kDevtoolsResourcesSize; ++i) { |
142 if (name == kDevtoolsResources[i].name) | 143 if (name == kDevtoolsResources[i].name) |
143 return kDevtoolsResources[i].value; | 144 return kDevtoolsResources[i].value; |
144 } | 145 } |
145 return -1; | 146 return -1; |
146 } | 147 } |
147 | 148 |
148 // static | 149 // static |
149 DevToolsHttpHandler* DevToolsHttpHandler::Start( | 150 DevToolsHttpHandler* DevToolsHttpHandler::Start( |
150 const net::StreamListenSocketFactory* socket_factory, | 151 scoped_ptr<net::ServerSocket> server_socket, |
151 const std::string& frontend_url, | 152 const std::string& frontend_url, |
152 DevToolsHttpHandlerDelegate* delegate) { | 153 DevToolsHttpHandlerDelegate* delegate) { |
153 DevToolsHttpHandlerImpl* http_handler = | 154 DevToolsHttpHandlerImpl* http_handler = |
154 new DevToolsHttpHandlerImpl(socket_factory, | 155 new DevToolsHttpHandlerImpl(server_socket.Pass(), |
155 frontend_url, | 156 frontend_url, |
156 delegate); | 157 delegate); |
157 http_handler->Start(); | 158 http_handler->Start(); |
158 return http_handler; | 159 return http_handler; |
159 } | 160 } |
160 | 161 |
161 DevToolsHttpHandlerImpl::~DevToolsHttpHandlerImpl() { | 162 DevToolsHttpHandlerImpl::~DevToolsHttpHandlerImpl() { |
162 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 163 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
163 // Stop() must be called prior to destruction. | 164 // Stop() must be called prior to destruction. |
164 DCHECK(server_.get() == NULL); | 165 DCHECK(server_.get() == NULL); |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
317 void DevToolsHttpHandlerImpl::OnWebSocketRequest( | 318 void DevToolsHttpHandlerImpl::OnWebSocketRequest( |
318 int connection_id, | 319 int connection_id, |
319 const net::HttpServerRequestInfo& request) { | 320 const net::HttpServerRequestInfo& request) { |
320 std::string browser_prefix = "/devtools/browser"; | 321 std::string browser_prefix = "/devtools/browser"; |
321 size_t browser_pos = request.path.find(browser_prefix); | 322 size_t browser_pos = request.path.find(browser_prefix); |
322 if (browser_pos == 0) { | 323 if (browser_pos == 0) { |
323 if (browser_target_) { | 324 if (browser_target_) { |
324 server_->Send500(connection_id, "Another client already attached"); | 325 server_->Send500(connection_id, "Another client already attached"); |
325 return; | 326 return; |
326 } | 327 } |
327 browser_target_ = new DevToolsBrowserTarget(server_.get(), connection_id); | 328 browser_target_ = new DevToolsBrowserTarget(server_->AsWeakPtr(), |
329 connection_id); | |
328 browser_target_->RegisterDomainHandler( | 330 browser_target_->RegisterDomainHandler( |
329 devtools::Tracing::kName, | 331 devtools::Tracing::kName, |
330 new DevToolsTracingHandler(DevToolsTracingHandler::Browser), | 332 new DevToolsTracingHandler(DevToolsTracingHandler::Browser), |
331 true /* handle on UI thread */); | 333 true /* handle on UI thread */); |
332 browser_target_->RegisterDomainHandler( | 334 browser_target_->RegisterDomainHandler( |
333 TetheringHandler::kDomain, | 335 TetheringHandler::kDomain, |
334 new TetheringHandler(delegate_.get()), | 336 new TetheringHandler(delegate_.get()), |
335 false /* handle on this thread */); | 337 false /* handle on this thread */); |
336 browser_target_->RegisterDomainHandler( | 338 browser_target_->RegisterDomainHandler( |
337 devtools::SystemInfo::kName, | 339 devtools::SystemInfo::kName, |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
598 return; | 600 return; |
599 } | 601 } |
600 | 602 |
601 if (agent->IsAttached()) { | 603 if (agent->IsAttached()) { |
602 Send500(connection_id, | 604 Send500(connection_id, |
603 "Target with given id is being inspected: " + page_id); | 605 "Target with given id is being inspected: " + page_id); |
604 return; | 606 return; |
605 } | 607 } |
606 | 608 |
607 DevToolsClientHostImpl* client_host = new DevToolsClientHostImpl( | 609 DevToolsClientHostImpl* client_host = new DevToolsClientHostImpl( |
608 thread_->message_loop(), server_.get(), connection_id); | 610 thread_->message_loop(), server_->AsWeakPtr(), connection_id); |
609 connection_to_client_host_ui_[connection_id] = client_host; | 611 connection_to_client_host_ui_[connection_id] = client_host; |
610 | 612 |
611 DevToolsManager::GetInstance()-> | 613 DevToolsManager::GetInstance()-> |
612 RegisterDevToolsClientHostFor(agent, client_host); | 614 RegisterDevToolsClientHostFor(agent, client_host); |
613 | 615 |
614 AcceptWebSocket(connection_id, request); | 616 AcceptWebSocket(connection_id, request); |
615 } | 617 } |
616 | 618 |
617 void DevToolsHttpHandlerImpl::OnWebSocketMessageUI( | 619 void DevToolsHttpHandlerImpl::OnWebSocketMessageUI( |
618 int connection_id, | 620 int connection_id, |
(...skipping 13 matching lines...) Expand all Loading... | |
632 if (it != connection_to_client_host_ui_.end()) { | 634 if (it != connection_to_client_host_ui_.end()) { |
633 DevToolsClientHostImpl* client_host = | 635 DevToolsClientHostImpl* client_host = |
634 static_cast<DevToolsClientHostImpl*>(it->second); | 636 static_cast<DevToolsClientHostImpl*>(it->second); |
635 DevToolsManager::GetInstance()->ClientHostClosing(client_host); | 637 DevToolsManager::GetInstance()->ClientHostClosing(client_host); |
636 delete client_host; | 638 delete client_host; |
637 connection_to_client_host_ui_.erase(connection_id); | 639 connection_to_client_host_ui_.erase(connection_id); |
638 } | 640 } |
639 } | 641 } |
640 | 642 |
641 DevToolsHttpHandlerImpl::DevToolsHttpHandlerImpl( | 643 DevToolsHttpHandlerImpl::DevToolsHttpHandlerImpl( |
642 const net::StreamListenSocketFactory* socket_factory, | 644 scoped_ptr<net::ServerSocket> server_socket, |
643 const std::string& frontend_url, | 645 const std::string& frontend_url, |
644 DevToolsHttpHandlerDelegate* delegate) | 646 DevToolsHttpHandlerDelegate* delegate) |
645 : frontend_url_(frontend_url), | 647 : frontend_url_(frontend_url), |
646 socket_factory_(socket_factory), | 648 server_socket_(server_socket.Pass()), |
647 delegate_(delegate) { | 649 delegate_(delegate) { |
648 if (frontend_url_.empty()) | 650 if (frontend_url_.empty()) |
649 frontend_url_ = "/devtools/devtools.html"; | 651 frontend_url_ = "/devtools/devtools.html"; |
650 | 652 |
651 // Balanced in ResetHandlerThreadAndRelease(). | 653 // Balanced in ResetHandlerThreadAndRelease(). |
652 AddRef(); | 654 AddRef(); |
653 } | 655 } |
654 | 656 |
655 // Runs on the handler thread | 657 // Runs on the handler thread |
656 void DevToolsHttpHandlerImpl::Init() { | 658 void DevToolsHttpHandlerImpl::Init() { |
657 server_ = new net::HttpServer(*socket_factory_.get(), this); | 659 server_.reset(new net::HttpServer(server_socket_.Pass(), this)); |
658 } | 660 } |
659 | 661 |
660 // Runs on the handler thread | 662 // Runs on the handler thread |
661 void DevToolsHttpHandlerImpl::Teardown() { | 663 void DevToolsHttpHandlerImpl::Teardown() { |
662 server_ = NULL; | 664 server_.reset(NULL); |
663 } | 665 } |
664 | 666 |
665 // Runs on FILE thread to make sure that it is serialized against | 667 // Runs on FILE thread to make sure that it is serialized against |
666 // {Start|Stop}HandlerThread and to allow calling pthread_join. | 668 // {Start|Stop}HandlerThread and to allow calling pthread_join. |
667 void DevToolsHttpHandlerImpl::StopHandlerThread() { | 669 void DevToolsHttpHandlerImpl::StopHandlerThread() { |
668 if (!thread_->message_loop()) | 670 if (!thread_->message_loop()) |
669 return; | 671 return; |
670 thread_->message_loop()->PostTask( | 672 thread_->message_loop()->PostTask( |
671 FROM_HERE, | 673 FROM_HERE, |
672 base::Bind(&DevToolsHttpHandlerImpl::Teardown, this)); | 674 base::Bind(&DevToolsHttpHandlerImpl::Teardown, this)); |
(...skipping 18 matching lines...) Expand all Loading... | |
691 std::string json_message; | 693 std::string json_message; |
692 scoped_ptr<base::Value> message_object(new base::StringValue(message)); | 694 scoped_ptr<base::Value> message_object(new base::StringValue(message)); |
693 base::JSONWriter::Write(message_object.get(), &json_message); | 695 base::JSONWriter::Write(message_object.get(), &json_message); |
694 | 696 |
695 net::HttpServerResponseInfo response(status_code); | 697 net::HttpServerResponseInfo response(status_code); |
696 response.SetBody(json_value + message, "application/json; charset=UTF-8"); | 698 response.SetBody(json_value + message, "application/json; charset=UTF-8"); |
697 | 699 |
698 thread_->message_loop()->PostTask( | 700 thread_->message_loop()->PostTask( |
699 FROM_HERE, | 701 FROM_HERE, |
700 base::Bind(&net::HttpServer::SendResponse, | 702 base::Bind(&net::HttpServer::SendResponse, |
701 server_.get(), | 703 server_->AsWeakPtr(), |
702 connection_id, | 704 connection_id, |
703 response)); | 705 response)); |
704 } | 706 } |
705 | 707 |
706 void DevToolsHttpHandlerImpl::Send200(int connection_id, | 708 void DevToolsHttpHandlerImpl::Send200(int connection_id, |
707 const std::string& data, | 709 const std::string& data, |
708 const std::string& mime_type) { | 710 const std::string& mime_type) { |
709 if (!thread_) | 711 if (!thread_) |
710 return; | 712 return; |
711 thread_->message_loop()->PostTask( | 713 thread_->message_loop()->PostTask( |
712 FROM_HERE, | 714 FROM_HERE, |
713 base::Bind(&net::HttpServer::Send200, | 715 base::Bind(&net::HttpServer::Send200, |
714 server_.get(), | 716 server_->AsWeakPtr(), |
715 connection_id, | 717 connection_id, |
716 data, | 718 data, |
717 mime_type)); | 719 mime_type)); |
718 } | 720 } |
719 | 721 |
720 void DevToolsHttpHandlerImpl::Send404(int connection_id) { | 722 void DevToolsHttpHandlerImpl::Send404(int connection_id) { |
721 if (!thread_) | 723 if (!thread_) |
722 return; | 724 return; |
723 thread_->message_loop()->PostTask( | 725 thread_->message_loop()->PostTask( |
724 FROM_HERE, | 726 FROM_HERE, |
725 base::Bind(&net::HttpServer::Send404, server_.get(), connection_id)); | 727 base::Bind(&net::HttpServer::Send404, |
728 server_->AsWeakPtr(), | |
729 connection_id)); | |
726 } | 730 } |
727 | 731 |
728 void DevToolsHttpHandlerImpl::Send500(int connection_id, | 732 void DevToolsHttpHandlerImpl::Send500(int connection_id, |
729 const std::string& message) { | 733 const std::string& message) { |
730 if (!thread_) | 734 if (!thread_) |
731 return; | 735 return; |
732 thread_->message_loop()->PostTask( | 736 thread_->message_loop()->PostTask( |
733 FROM_HERE, | 737 FROM_HERE, |
734 base::Bind(&net::HttpServer::Send500, server_.get(), connection_id, | 738 base::Bind(&net::HttpServer::Send500, |
739 server_->AsWeakPtr(), | |
740 connection_id, | |
735 message)); | 741 message)); |
736 } | 742 } |
737 | 743 |
738 void DevToolsHttpHandlerImpl::AcceptWebSocket( | 744 void DevToolsHttpHandlerImpl::AcceptWebSocket( |
739 int connection_id, | 745 int connection_id, |
740 const net::HttpServerRequestInfo& request) { | 746 const net::HttpServerRequestInfo& request) { |
741 if (!thread_) | 747 if (!thread_) |
742 return; | 748 return; |
743 thread_->message_loop()->PostTask( | 749 thread_->message_loop()->PostTask( |
744 FROM_HERE, | 750 FROM_HERE, |
745 base::Bind(&net::HttpServer::AcceptWebSocket, server_.get(), | 751 base::Bind(&net::HttpServer::AcceptWebSocket, |
746 connection_id, request)); | 752 server_->AsWeakPtr(), |
753 connection_id, | |
754 request)); | |
747 } | 755 } |
748 | 756 |
749 base::DictionaryValue* DevToolsHttpHandlerImpl::SerializeTarget( | 757 base::DictionaryValue* DevToolsHttpHandlerImpl::SerializeTarget( |
750 const DevToolsTarget& target, | 758 const DevToolsTarget& target, |
751 const std::string& host) { | 759 const std::string& host) { |
752 base::DictionaryValue* dictionary = new base::DictionaryValue; | 760 base::DictionaryValue* dictionary = new base::DictionaryValue; |
753 | 761 |
754 std::string id = target.GetId(); | 762 std::string id = target.GetId(); |
755 dictionary->SetString(kTargetIdField, id); | 763 dictionary->SetString(kTargetIdField, id); |
756 dictionary->SetString(kTargetTypeField, target.GetType()); | 764 dictionary->SetString(kTargetTypeField, target.GetType()); |
(...skipping 23 matching lines...) Expand all Loading... | |
780 id.c_str(), | 788 id.c_str(), |
781 host); | 789 host); |
782 dictionary->SetString( | 790 dictionary->SetString( |
783 kTargetDevtoolsFrontendUrlField, devtools_frontend_url); | 791 kTargetDevtoolsFrontendUrlField, devtools_frontend_url); |
784 } | 792 } |
785 | 793 |
786 return dictionary; | 794 return dictionary; |
787 } | 795 } |
788 | 796 |
789 } // namespace content | 797 } // namespace content |
OLD | NEW |