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 <sstream> | 8 #include <sstream> |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 23 matching lines...) Expand all Loading... |
34 #include "content/public/common/url_constants.h" | 34 #include "content/public/common/url_constants.h" |
35 #include "content/public/common/user_agent.h" | 35 #include "content/public/common/user_agent.h" |
36 #include "content/public/common/user_agent.h" | 36 #include "content/public/common/user_agent.h" |
37 #include "grit/devtools_resources_map.h" | 37 #include "grit/devtools_resources_map.h" |
38 #include "net/base/escape.h" | 38 #include "net/base/escape.h" |
39 #include "net/base/io_buffer.h" | 39 #include "net/base/io_buffer.h" |
40 #include "net/base/ip_endpoint.h" | 40 #include "net/base/ip_endpoint.h" |
41 #include "net/base/net_errors.h" | 41 #include "net/base/net_errors.h" |
42 #include "net/server/http_server_request_info.h" | 42 #include "net/server/http_server_request_info.h" |
43 #include "net/server/http_server_response_info.h" | 43 #include "net/server/http_server_response_info.h" |
| 44 #include "net/socket/server_socket.h" |
44 | 45 |
45 #if defined(OS_ANDROID) | 46 #if defined(OS_ANDROID) |
46 #include "base/android/build_info.h" | 47 #include "base/android/build_info.h" |
47 #endif | 48 #endif |
48 | 49 |
49 namespace content { | 50 namespace content { |
50 | 51 |
51 namespace { | 52 namespace { |
52 | 53 |
53 const base::FilePath::CharType kDevToolsActivePortFileName[] = | 54 const base::FilePath::CharType kDevToolsActivePortFileName[] = |
54 FILE_PATH_LITERAL("DevToolsActivePort"); | 55 FILE_PATH_LITERAL("DevToolsActivePort"); |
55 | 56 |
56 const char kDevToolsHandlerThreadName[] = "Chrome_DevToolsHandlerThread"; | 57 const char kDevToolsHandlerThreadName[] = "Chrome_DevToolsHandlerThread"; |
57 | 58 |
58 const char kThumbUrlPrefix[] = "/thumb/"; | 59 const char kThumbUrlPrefix[] = "/thumb/"; |
59 const char kPageUrlPrefix[] = "/devtools/page/"; | 60 const char kPageUrlPrefix[] = "/devtools/page/"; |
60 | 61 |
61 const char kTargetIdField[] = "id"; | 62 const char kTargetIdField[] = "id"; |
62 const char kTargetParentIdField[] = "parentId"; | 63 const char kTargetParentIdField[] = "parentId"; |
63 const char kTargetTypeField[] = "type"; | 64 const char kTargetTypeField[] = "type"; |
64 const char kTargetTitleField[] = "title"; | 65 const char kTargetTitleField[] = "title"; |
65 const char kTargetDescriptionField[] = "description"; | 66 const char kTargetDescriptionField[] = "description"; |
66 const char kTargetUrlField[] = "url"; | 67 const char kTargetUrlField[] = "url"; |
67 const char kTargetThumbnailUrlField[] = "thumbnailUrl"; | 68 const char kTargetThumbnailUrlField[] = "thumbnailUrl"; |
68 const char kTargetFaviconUrlField[] = "faviconUrl"; | 69 const char kTargetFaviconUrlField[] = "faviconUrl"; |
69 const char kTargetWebSocketDebuggerUrlField[] = "webSocketDebuggerUrl"; | 70 const char kTargetWebSocketDebuggerUrlField[] = "webSocketDebuggerUrl"; |
70 const char kTargetDevtoolsFrontendUrlField[] = "devtoolsFrontendUrl"; | 71 const char kTargetDevtoolsFrontendUrlField[] = "devtoolsFrontendUrl"; |
71 | 72 |
| 73 // Maximum write buffer size of devtools websocket. |
| 74 const int32 kSendBufferSizeForDevToolsWebSocket = 100 * 1024 * 1024; // 100Mb |
| 75 |
72 // An internal implementation of DevToolsClientHost that delegates | 76 // An internal implementation of DevToolsClientHost that delegates |
73 // messages sent for DevToolsClient to a DebuggerShell instance. | 77 // messages sent for DevToolsClient to a DebuggerShell instance. |
74 class DevToolsClientHostImpl : public DevToolsClientHost { | 78 class DevToolsClientHostImpl : public DevToolsClientHost { |
75 public: | 79 public: |
76 DevToolsClientHostImpl(base::MessageLoop* message_loop, | 80 DevToolsClientHostImpl(base::MessageLoop* message_loop, |
77 net::HttpServer* server, | 81 base::WeakPtr<net::HttpServer> server, |
78 int connection_id) | 82 int connection_id) |
79 : message_loop_(message_loop), | 83 : message_loop_(message_loop), |
80 server_(server), | 84 server_(server), |
81 connection_id_(connection_id), | 85 connection_id_(connection_id), |
82 is_closed_(false), | 86 is_closed_(false), |
83 detach_reason_("target_closed") {} | 87 detach_reason_("target_closed") {} |
84 | 88 |
85 virtual ~DevToolsClientHostImpl() {} | 89 virtual ~DevToolsClientHostImpl() {} |
86 | 90 |
87 // DevToolsClientHost interface | 91 // DevToolsClientHost interface |
(...skipping 28 matching lines...) Expand all Loading... |
116 connection_id_, | 120 connection_id_, |
117 data)); | 121 data)); |
118 } | 122 } |
119 | 123 |
120 virtual void ReplacedWithAnotherClient() OVERRIDE { | 124 virtual void ReplacedWithAnotherClient() OVERRIDE { |
121 detach_reason_ = "replaced_with_devtools"; | 125 detach_reason_ = "replaced_with_devtools"; |
122 } | 126 } |
123 | 127 |
124 private: | 128 private: |
125 base::MessageLoop* message_loop_; | 129 base::MessageLoop* message_loop_; |
126 net::HttpServer* server_; | 130 base::WeakPtr<net::HttpServer> server_; |
127 int connection_id_; | 131 int connection_id_; |
128 bool is_closed_; | 132 bool is_closed_; |
129 std::string detach_reason_; | 133 std::string detach_reason_; |
130 }; | 134 }; |
131 | 135 |
132 static bool TimeComparator(const DevToolsTarget* target1, | 136 static bool TimeComparator(const DevToolsTarget* target1, |
133 const DevToolsTarget* target2) { | 137 const DevToolsTarget* target2) { |
134 return target1->GetLastActivityTime() > target2->GetLastActivityTime(); | 138 return target1->GetLastActivityTime() > target2->GetLastActivityTime(); |
135 } | 139 } |
136 | 140 |
137 } // namespace | 141 } // namespace |
138 | 142 |
139 // static | 143 // static |
140 bool DevToolsHttpHandler::IsSupportedProtocolVersion( | 144 bool DevToolsHttpHandler::IsSupportedProtocolVersion( |
141 const std::string& version) { | 145 const std::string& version) { |
142 return devtools::IsSupportedProtocolVersion(version); | 146 return devtools::IsSupportedProtocolVersion(version); |
143 } | 147 } |
144 | 148 |
145 // static | 149 // static |
146 int DevToolsHttpHandler::GetFrontendResourceId(const std::string& name) { | 150 int DevToolsHttpHandler::GetFrontendResourceId(const std::string& name) { |
147 for (size_t i = 0; i < kDevtoolsResourcesSize; ++i) { | 151 for (size_t i = 0; i < kDevtoolsResourcesSize; ++i) { |
148 if (name == kDevtoolsResources[i].name) | 152 if (name == kDevtoolsResources[i].name) |
149 return kDevtoolsResources[i].value; | 153 return kDevtoolsResources[i].value; |
150 } | 154 } |
151 return -1; | 155 return -1; |
152 } | 156 } |
153 | 157 |
154 // static | 158 // static |
155 DevToolsHttpHandler* DevToolsHttpHandler::Start( | 159 DevToolsHttpHandler* DevToolsHttpHandler::Start( |
156 const net::StreamListenSocketFactory* socket_factory, | 160 scoped_ptr<net::ServerSocketFactory> server_socket_factory, |
157 const std::string& frontend_url, | 161 const std::string& frontend_url, |
158 DevToolsHttpHandlerDelegate* delegate, | 162 DevToolsHttpHandlerDelegate* delegate, |
159 const base::FilePath& active_port_output_directory) { | 163 const base::FilePath& active_port_output_directory) { |
160 DevToolsHttpHandlerImpl* http_handler = | 164 DevToolsHttpHandlerImpl* http_handler = |
161 new DevToolsHttpHandlerImpl(socket_factory, | 165 new DevToolsHttpHandlerImpl(server_socket_factory.Pass(), |
162 frontend_url, | 166 frontend_url, |
163 delegate, | 167 delegate, |
164 active_port_output_directory); | 168 active_port_output_directory); |
165 http_handler->Start(); | 169 http_handler->Start(); |
166 return http_handler; | 170 return http_handler; |
167 } | 171 } |
168 | 172 |
169 DevToolsHttpHandlerImpl::~DevToolsHttpHandlerImpl() { | 173 DevToolsHttpHandlerImpl::~DevToolsHttpHandlerImpl() { |
170 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 174 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
171 // Stop() must be called prior to destruction. | 175 // Stop() must be called prior to destruction. |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
325 void DevToolsHttpHandlerImpl::OnWebSocketRequest( | 329 void DevToolsHttpHandlerImpl::OnWebSocketRequest( |
326 int connection_id, | 330 int connection_id, |
327 const net::HttpServerRequestInfo& request) { | 331 const net::HttpServerRequestInfo& request) { |
328 std::string browser_prefix = "/devtools/browser"; | 332 std::string browser_prefix = "/devtools/browser"; |
329 size_t browser_pos = request.path.find(browser_prefix); | 333 size_t browser_pos = request.path.find(browser_prefix); |
330 if (browser_pos == 0) { | 334 if (browser_pos == 0) { |
331 if (browser_target_) { | 335 if (browser_target_) { |
332 server_->Send500(connection_id, "Another client already attached"); | 336 server_->Send500(connection_id, "Another client already attached"); |
333 return; | 337 return; |
334 } | 338 } |
335 browser_target_ = new DevToolsBrowserTarget(server_.get(), connection_id); | 339 browser_target_ = new DevToolsBrowserTarget(server_->GetWeakPtr(), |
| 340 connection_id); |
336 browser_target_->RegisterDomainHandler( | 341 browser_target_->RegisterDomainHandler( |
337 devtools::Tracing::kName, | 342 devtools::Tracing::kName, |
338 new DevToolsTracingHandler(DevToolsTracingHandler::Browser), | 343 new DevToolsTracingHandler(DevToolsTracingHandler::Browser), |
339 true /* handle on UI thread */); | 344 true /* handle on UI thread */); |
340 browser_target_->RegisterDomainHandler( | 345 browser_target_->RegisterDomainHandler( |
341 TetheringHandler::kDomain, | 346 TetheringHandler::kDomain, |
342 new TetheringHandler(delegate_.get()), | 347 new TetheringHandler(delegate_.get()), |
343 false /* handle on this thread */); | 348 false /* handle on this thread */); |
344 browser_target_->RegisterDomainHandler( | 349 browser_target_->RegisterDomainHandler( |
345 devtools::SystemInfo::kName, | 350 devtools::SystemInfo::kName, |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
606 return; | 611 return; |
607 } | 612 } |
608 | 613 |
609 if (agent->IsAttached()) { | 614 if (agent->IsAttached()) { |
610 Send500(connection_id, | 615 Send500(connection_id, |
611 "Target with given id is being inspected: " + page_id); | 616 "Target with given id is being inspected: " + page_id); |
612 return; | 617 return; |
613 } | 618 } |
614 | 619 |
615 DevToolsClientHostImpl* client_host = new DevToolsClientHostImpl( | 620 DevToolsClientHostImpl* client_host = new DevToolsClientHostImpl( |
616 thread_->message_loop(), server_.get(), connection_id); | 621 thread_->message_loop(), server_->GetWeakPtr(), connection_id); |
617 connection_to_client_host_ui_[connection_id] = client_host; | 622 connection_to_client_host_ui_[connection_id] = client_host; |
618 | 623 |
619 DevToolsManager::GetInstance()-> | 624 DevToolsManager::GetInstance()-> |
620 RegisterDevToolsClientHostFor(agent, client_host); | 625 RegisterDevToolsClientHostFor(agent, client_host); |
621 | 626 |
622 AcceptWebSocket(connection_id, request); | 627 AcceptWebSocket(connection_id, request); |
623 } | 628 } |
624 | 629 |
625 void DevToolsHttpHandlerImpl::OnWebSocketMessageUI( | 630 void DevToolsHttpHandlerImpl::OnWebSocketMessageUI( |
626 int connection_id, | 631 int connection_id, |
(...skipping 13 matching lines...) Expand all Loading... |
640 if (it != connection_to_client_host_ui_.end()) { | 645 if (it != connection_to_client_host_ui_.end()) { |
641 DevToolsClientHostImpl* client_host = | 646 DevToolsClientHostImpl* client_host = |
642 static_cast<DevToolsClientHostImpl*>(it->second); | 647 static_cast<DevToolsClientHostImpl*>(it->second); |
643 DevToolsManager::GetInstance()->ClientHostClosing(client_host); | 648 DevToolsManager::GetInstance()->ClientHostClosing(client_host); |
644 delete client_host; | 649 delete client_host; |
645 connection_to_client_host_ui_.erase(connection_id); | 650 connection_to_client_host_ui_.erase(connection_id); |
646 } | 651 } |
647 } | 652 } |
648 | 653 |
649 DevToolsHttpHandlerImpl::DevToolsHttpHandlerImpl( | 654 DevToolsHttpHandlerImpl::DevToolsHttpHandlerImpl( |
650 const net::StreamListenSocketFactory* socket_factory, | 655 scoped_ptr<net::ServerSocketFactory> server_socket_factory, |
651 const std::string& frontend_url, | 656 const std::string& frontend_url, |
652 DevToolsHttpHandlerDelegate* delegate, | 657 DevToolsHttpHandlerDelegate* delegate, |
653 const base::FilePath& active_port_output_directory) | 658 const base::FilePath& active_port_output_directory) |
654 : frontend_url_(frontend_url), | 659 : frontend_url_(frontend_url), |
655 socket_factory_(socket_factory), | 660 server_socket_factory_(server_socket_factory.Pass()), |
656 delegate_(delegate), | 661 delegate_(delegate), |
657 active_port_output_directory_(active_port_output_directory) { | 662 active_port_output_directory_(active_port_output_directory) { |
658 if (frontend_url_.empty()) | 663 if (frontend_url_.empty()) |
659 frontend_url_ = "/devtools/devtools.html"; | 664 frontend_url_ = "/devtools/devtools.html"; |
660 | 665 |
661 // Balanced in ResetHandlerThreadAndRelease(). | 666 // Balanced in ResetHandlerThreadAndRelease(). |
662 AddRef(); | 667 AddRef(); |
663 } | 668 } |
664 | 669 |
665 // Runs on the handler thread | 670 // Runs on the handler thread |
666 void DevToolsHttpHandlerImpl::Init() { | 671 void DevToolsHttpHandlerImpl::Init() { |
667 server_ = new net::HttpServer(*socket_factory_.get(), this); | 672 server_.reset(new net::HttpServer(server_socket_factory_->CreateAndListen(), |
| 673 this)); |
668 if (!active_port_output_directory_.empty()) | 674 if (!active_port_output_directory_.empty()) |
669 WriteActivePortToUserProfile(); | 675 WriteActivePortToUserProfile(); |
670 } | 676 } |
671 | 677 |
672 // Runs on the handler thread | 678 // Runs on the handler thread |
673 void DevToolsHttpHandlerImpl::Teardown() { | 679 void DevToolsHttpHandlerImpl::Teardown() { |
674 server_ = NULL; | 680 server_.reset(NULL); |
675 } | 681 } |
676 | 682 |
677 // Runs on FILE thread to make sure that it is serialized against | 683 // Runs on FILE thread to make sure that it is serialized against |
678 // {Start|Stop}HandlerThread and to allow calling pthread_join. | 684 // {Start|Stop}HandlerThread and to allow calling pthread_join. |
679 void DevToolsHttpHandlerImpl::StopHandlerThread() { | 685 void DevToolsHttpHandlerImpl::StopHandlerThread() { |
680 if (!thread_->message_loop()) | 686 if (!thread_->message_loop()) |
681 return; | 687 return; |
682 thread_->message_loop()->PostTask( | 688 thread_->message_loop()->PostTask( |
683 FROM_HERE, | 689 FROM_HERE, |
684 base::Bind(&DevToolsHttpHandlerImpl::Teardown, this)); | 690 base::Bind(&DevToolsHttpHandlerImpl::Teardown, this)); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
724 std::string json_message; | 730 std::string json_message; |
725 scoped_ptr<base::Value> message_object(new base::StringValue(message)); | 731 scoped_ptr<base::Value> message_object(new base::StringValue(message)); |
726 base::JSONWriter::Write(message_object.get(), &json_message); | 732 base::JSONWriter::Write(message_object.get(), &json_message); |
727 | 733 |
728 net::HttpServerResponseInfo response(status_code); | 734 net::HttpServerResponseInfo response(status_code); |
729 response.SetBody(json_value + message, "application/json; charset=UTF-8"); | 735 response.SetBody(json_value + message, "application/json; charset=UTF-8"); |
730 | 736 |
731 thread_->message_loop()->PostTask( | 737 thread_->message_loop()->PostTask( |
732 FROM_HERE, | 738 FROM_HERE, |
733 base::Bind(&net::HttpServer::SendResponse, | 739 base::Bind(&net::HttpServer::SendResponse, |
734 server_.get(), | 740 server_->GetWeakPtr(), |
735 connection_id, | 741 connection_id, |
736 response)); | 742 response)); |
737 } | 743 } |
738 | 744 |
739 void DevToolsHttpHandlerImpl::Send200(int connection_id, | 745 void DevToolsHttpHandlerImpl::Send200(int connection_id, |
740 const std::string& data, | 746 const std::string& data, |
741 const std::string& mime_type) { | 747 const std::string& mime_type) { |
742 if (!thread_) | 748 if (!thread_) |
743 return; | 749 return; |
744 thread_->message_loop()->PostTask( | 750 thread_->message_loop()->PostTask( |
745 FROM_HERE, | 751 FROM_HERE, |
746 base::Bind(&net::HttpServer::Send200, | 752 base::Bind(&net::HttpServer::Send200, |
747 server_.get(), | 753 server_->GetWeakPtr(), |
748 connection_id, | 754 connection_id, |
749 data, | 755 data, |
750 mime_type)); | 756 mime_type)); |
751 } | 757 } |
752 | 758 |
753 void DevToolsHttpHandlerImpl::Send404(int connection_id) { | 759 void DevToolsHttpHandlerImpl::Send404(int connection_id) { |
754 if (!thread_) | 760 if (!thread_) |
755 return; | 761 return; |
756 thread_->message_loop()->PostTask( | 762 thread_->message_loop()->PostTask( |
757 FROM_HERE, | 763 FROM_HERE, |
758 base::Bind(&net::HttpServer::Send404, server_.get(), connection_id)); | 764 base::Bind(&net::HttpServer::Send404, |
| 765 server_->GetWeakPtr(), |
| 766 connection_id)); |
759 } | 767 } |
760 | 768 |
761 void DevToolsHttpHandlerImpl::Send500(int connection_id, | 769 void DevToolsHttpHandlerImpl::Send500(int connection_id, |
762 const std::string& message) { | 770 const std::string& message) { |
763 if (!thread_) | 771 if (!thread_) |
764 return; | 772 return; |
765 thread_->message_loop()->PostTask( | 773 thread_->message_loop()->PostTask( |
766 FROM_HERE, | 774 FROM_HERE, |
767 base::Bind(&net::HttpServer::Send500, server_.get(), connection_id, | 775 base::Bind(&net::HttpServer::Send500, |
| 776 server_->GetWeakPtr(), |
| 777 connection_id, |
768 message)); | 778 message)); |
769 } | 779 } |
770 | 780 |
771 void DevToolsHttpHandlerImpl::AcceptWebSocket( | 781 void DevToolsHttpHandlerImpl::AcceptWebSocket( |
772 int connection_id, | 782 int connection_id, |
773 const net::HttpServerRequestInfo& request) { | 783 const net::HttpServerRequestInfo& request) { |
774 if (!thread_) | 784 if (!thread_) |
775 return; | 785 return; |
776 thread_->message_loop()->PostTask( | 786 thread_->message_loop()->PostTask( |
777 FROM_HERE, | 787 FROM_HERE, |
778 base::Bind(&net::HttpServer::AcceptWebSocket, server_.get(), | 788 base::Bind(&net::HttpServer::SetSendBufferSize, |
779 connection_id, request)); | 789 server_->GetWeakPtr(), |
| 790 connection_id, |
| 791 kSendBufferSizeForDevToolsWebSocket)); |
| 792 thread_->message_loop()->PostTask( |
| 793 FROM_HERE, |
| 794 base::Bind(&net::HttpServer::AcceptWebSocket, |
| 795 server_->GetWeakPtr(), |
| 796 connection_id, |
| 797 request)); |
780 } | 798 } |
781 | 799 |
782 base::DictionaryValue* DevToolsHttpHandlerImpl::SerializeTarget( | 800 base::DictionaryValue* DevToolsHttpHandlerImpl::SerializeTarget( |
783 const DevToolsTarget& target, | 801 const DevToolsTarget& target, |
784 const std::string& host) { | 802 const std::string& host) { |
785 base::DictionaryValue* dictionary = new base::DictionaryValue; | 803 base::DictionaryValue* dictionary = new base::DictionaryValue; |
786 | 804 |
787 std::string id = target.GetId(); | 805 std::string id = target.GetId(); |
788 dictionary->SetString(kTargetIdField, id); | 806 dictionary->SetString(kTargetIdField, id); |
789 std::string parent_id = target.GetParentId(); | 807 std::string parent_id = target.GetParentId(); |
(...skipping 26 matching lines...) Expand all Loading... |
816 id.c_str(), | 834 id.c_str(), |
817 host); | 835 host); |
818 dictionary->SetString( | 836 dictionary->SetString( |
819 kTargetDevtoolsFrontendUrlField, devtools_frontend_url); | 837 kTargetDevtoolsFrontendUrlField, devtools_frontend_url); |
820 } | 838 } |
821 | 839 |
822 return dictionary; | 840 return dictionary; |
823 } | 841 } |
824 | 842 |
825 } // namespace content | 843 } // namespace content |
OLD | NEW |