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 |
| 67 // Maximum write buffer size of devtools websocket. |
| 68 const int32 kSendBufferSizeForDevToolsWebSocket = 100 * 1024 * 1024; // 100Mb |
| 69 |
66 // An internal implementation of DevToolsClientHost that delegates | 70 // An internal implementation of DevToolsClientHost that delegates |
67 // messages sent for DevToolsClient to a DebuggerShell instance. | 71 // messages sent for DevToolsClient to a DebuggerShell instance. |
68 class DevToolsClientHostImpl : public DevToolsClientHost { | 72 class DevToolsClientHostImpl : public DevToolsClientHost { |
69 public: | 73 public: |
70 DevToolsClientHostImpl(base::MessageLoop* message_loop, | 74 DevToolsClientHostImpl(base::MessageLoop* message_loop, |
71 net::HttpServer* server, | 75 base::WeakPtr<net::HttpServer> server, |
72 int connection_id) | 76 int connection_id) |
73 : message_loop_(message_loop), | 77 : message_loop_(message_loop), |
74 server_(server), | 78 server_(server), |
75 connection_id_(connection_id), | 79 connection_id_(connection_id), |
76 is_closed_(false), | 80 is_closed_(false), |
77 detach_reason_("target_closed") {} | 81 detach_reason_("target_closed") {} |
78 | 82 |
79 virtual ~DevToolsClientHostImpl() {} | 83 virtual ~DevToolsClientHostImpl() {} |
80 | 84 |
81 // DevToolsClientHost interface | 85 // DevToolsClientHost interface |
(...skipping 28 matching lines...) Expand all Loading... |
110 connection_id_, | 114 connection_id_, |
111 data)); | 115 data)); |
112 } | 116 } |
113 | 117 |
114 virtual void ReplacedWithAnotherClient() OVERRIDE { | 118 virtual void ReplacedWithAnotherClient() OVERRIDE { |
115 detach_reason_ = "replaced_with_devtools"; | 119 detach_reason_ = "replaced_with_devtools"; |
116 } | 120 } |
117 | 121 |
118 private: | 122 private: |
119 base::MessageLoop* message_loop_; | 123 base::MessageLoop* message_loop_; |
120 net::HttpServer* server_; | 124 base::WeakPtr<net::HttpServer> server_; |
121 int connection_id_; | 125 int connection_id_; |
122 bool is_closed_; | 126 bool is_closed_; |
123 std::string detach_reason_; | 127 std::string detach_reason_; |
124 }; | 128 }; |
125 | 129 |
126 static bool TimeComparator(const DevToolsTarget* target1, | 130 static bool TimeComparator(const DevToolsTarget* target1, |
127 const DevToolsTarget* target2) { | 131 const DevToolsTarget* target2) { |
128 return target1->GetLastActivityTime() > target2->GetLastActivityTime(); | 132 return target1->GetLastActivityTime() > target2->GetLastActivityTime(); |
129 } | 133 } |
130 | 134 |
131 } // namespace | 135 } // namespace |
132 | 136 |
133 // static | 137 // static |
134 bool DevToolsHttpHandler::IsSupportedProtocolVersion( | 138 bool DevToolsHttpHandler::IsSupportedProtocolVersion( |
135 const std::string& version) { | 139 const std::string& version) { |
136 return devtools::IsSupportedProtocolVersion(version); | 140 return devtools::IsSupportedProtocolVersion(version); |
137 } | 141 } |
138 | 142 |
139 // static | 143 // static |
140 int DevToolsHttpHandler::GetFrontendResourceId(const std::string& name) { | 144 int DevToolsHttpHandler::GetFrontendResourceId(const std::string& name) { |
141 for (size_t i = 0; i < kDevtoolsResourcesSize; ++i) { | 145 for (size_t i = 0; i < kDevtoolsResourcesSize; ++i) { |
142 if (name == kDevtoolsResources[i].name) | 146 if (name == kDevtoolsResources[i].name) |
143 return kDevtoolsResources[i].value; | 147 return kDevtoolsResources[i].value; |
144 } | 148 } |
145 return -1; | 149 return -1; |
146 } | 150 } |
147 | 151 |
148 // static | 152 // static |
149 DevToolsHttpHandler* DevToolsHttpHandler::Start( | 153 DevToolsHttpHandler* DevToolsHttpHandler::Start( |
150 const net::StreamListenSocketFactory* socket_factory, | 154 scoped_ptr<net::ServerSocketFactory> server_socket_factory, |
151 const std::string& frontend_url, | 155 const std::string& frontend_url, |
152 DevToolsHttpHandlerDelegate* delegate) { | 156 DevToolsHttpHandlerDelegate* delegate) { |
153 DevToolsHttpHandlerImpl* http_handler = | 157 DevToolsHttpHandlerImpl* http_handler = |
154 new DevToolsHttpHandlerImpl(socket_factory, | 158 new DevToolsHttpHandlerImpl(server_socket_factory.Pass(), |
155 frontend_url, | 159 frontend_url, |
156 delegate); | 160 delegate); |
157 http_handler->Start(); | 161 http_handler->Start(); |
158 return http_handler; | 162 return http_handler; |
159 } | 163 } |
160 | 164 |
161 DevToolsHttpHandlerImpl::~DevToolsHttpHandlerImpl() { | 165 DevToolsHttpHandlerImpl::~DevToolsHttpHandlerImpl() { |
162 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 166 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
163 // Stop() must be called prior to destruction. | 167 // Stop() must be called prior to destruction. |
164 DCHECK(server_.get() == NULL); | 168 DCHECK(server_.get() == NULL); |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
317 void DevToolsHttpHandlerImpl::OnWebSocketRequest( | 321 void DevToolsHttpHandlerImpl::OnWebSocketRequest( |
318 int connection_id, | 322 int connection_id, |
319 const net::HttpServerRequestInfo& request) { | 323 const net::HttpServerRequestInfo& request) { |
320 std::string browser_prefix = "/devtools/browser"; | 324 std::string browser_prefix = "/devtools/browser"; |
321 size_t browser_pos = request.path.find(browser_prefix); | 325 size_t browser_pos = request.path.find(browser_prefix); |
322 if (browser_pos == 0) { | 326 if (browser_pos == 0) { |
323 if (browser_target_) { | 327 if (browser_target_) { |
324 server_->Send500(connection_id, "Another client already attached"); | 328 server_->Send500(connection_id, "Another client already attached"); |
325 return; | 329 return; |
326 } | 330 } |
327 browser_target_ = new DevToolsBrowserTarget(server_.get(), connection_id); | 331 browser_target_ = new DevToolsBrowserTarget(server_->GetWeakPtr(), |
| 332 connection_id); |
328 browser_target_->RegisterDomainHandler( | 333 browser_target_->RegisterDomainHandler( |
329 devtools::Tracing::kName, | 334 devtools::Tracing::kName, |
330 new DevToolsTracingHandler(DevToolsTracingHandler::Browser), | 335 new DevToolsTracingHandler(DevToolsTracingHandler::Browser), |
331 true /* handle on UI thread */); | 336 true /* handle on UI thread */); |
332 browser_target_->RegisterDomainHandler( | 337 browser_target_->RegisterDomainHandler( |
333 TetheringHandler::kDomain, | 338 TetheringHandler::kDomain, |
334 new TetheringHandler(delegate_.get()), | 339 new TetheringHandler(delegate_.get()), |
335 false /* handle on this thread */); | 340 false /* handle on this thread */); |
336 browser_target_->RegisterDomainHandler( | 341 browser_target_->RegisterDomainHandler( |
337 devtools::SystemInfo::kName, | 342 devtools::SystemInfo::kName, |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
598 return; | 603 return; |
599 } | 604 } |
600 | 605 |
601 if (agent->IsAttached()) { | 606 if (agent->IsAttached()) { |
602 Send500(connection_id, | 607 Send500(connection_id, |
603 "Target with given id is being inspected: " + page_id); | 608 "Target with given id is being inspected: " + page_id); |
604 return; | 609 return; |
605 } | 610 } |
606 | 611 |
607 DevToolsClientHostImpl* client_host = new DevToolsClientHostImpl( | 612 DevToolsClientHostImpl* client_host = new DevToolsClientHostImpl( |
608 thread_->message_loop(), server_.get(), connection_id); | 613 thread_->message_loop(), server_->GetWeakPtr(), connection_id); |
609 connection_to_client_host_ui_[connection_id] = client_host; | 614 connection_to_client_host_ui_[connection_id] = client_host; |
610 | 615 |
611 DevToolsManager::GetInstance()-> | 616 DevToolsManager::GetInstance()-> |
612 RegisterDevToolsClientHostFor(agent, client_host); | 617 RegisterDevToolsClientHostFor(agent, client_host); |
613 | 618 |
614 AcceptWebSocket(connection_id, request); | 619 AcceptWebSocket(connection_id, request); |
615 } | 620 } |
616 | 621 |
617 void DevToolsHttpHandlerImpl::OnWebSocketMessageUI( | 622 void DevToolsHttpHandlerImpl::OnWebSocketMessageUI( |
618 int connection_id, | 623 int connection_id, |
(...skipping 13 matching lines...) Expand all Loading... |
632 if (it != connection_to_client_host_ui_.end()) { | 637 if (it != connection_to_client_host_ui_.end()) { |
633 DevToolsClientHostImpl* client_host = | 638 DevToolsClientHostImpl* client_host = |
634 static_cast<DevToolsClientHostImpl*>(it->second); | 639 static_cast<DevToolsClientHostImpl*>(it->second); |
635 DevToolsManager::GetInstance()->ClientHostClosing(client_host); | 640 DevToolsManager::GetInstance()->ClientHostClosing(client_host); |
636 delete client_host; | 641 delete client_host; |
637 connection_to_client_host_ui_.erase(connection_id); | 642 connection_to_client_host_ui_.erase(connection_id); |
638 } | 643 } |
639 } | 644 } |
640 | 645 |
641 DevToolsHttpHandlerImpl::DevToolsHttpHandlerImpl( | 646 DevToolsHttpHandlerImpl::DevToolsHttpHandlerImpl( |
642 const net::StreamListenSocketFactory* socket_factory, | 647 scoped_ptr<net::ServerSocketFactory> server_socket_factory, |
643 const std::string& frontend_url, | 648 const std::string& frontend_url, |
644 DevToolsHttpHandlerDelegate* delegate) | 649 DevToolsHttpHandlerDelegate* delegate) |
645 : frontend_url_(frontend_url), | 650 : frontend_url_(frontend_url), |
646 socket_factory_(socket_factory), | 651 server_socket_factory_(server_socket_factory.Pass()), |
647 delegate_(delegate) { | 652 delegate_(delegate) { |
648 if (frontend_url_.empty()) | 653 if (frontend_url_.empty()) |
649 frontend_url_ = "/devtools/devtools.html"; | 654 frontend_url_ = "/devtools/devtools.html"; |
650 | 655 |
651 // Balanced in ResetHandlerThreadAndRelease(). | 656 // Balanced in ResetHandlerThreadAndRelease(). |
652 AddRef(); | 657 AddRef(); |
653 } | 658 } |
654 | 659 |
655 // Runs on the handler thread | 660 // Runs on the handler thread |
656 void DevToolsHttpHandlerImpl::Init() { | 661 void DevToolsHttpHandlerImpl::Init() { |
657 server_ = new net::HttpServer(*socket_factory_.get(), this); | 662 server_.reset(new net::HttpServer(server_socket_factory_->CreateAndListen(), |
| 663 this)); |
658 } | 664 } |
659 | 665 |
660 // Runs on the handler thread | 666 // Runs on the handler thread |
661 void DevToolsHttpHandlerImpl::Teardown() { | 667 void DevToolsHttpHandlerImpl::Teardown() { |
662 server_ = NULL; | 668 server_.reset(NULL); |
663 } | 669 } |
664 | 670 |
665 // Runs on FILE thread to make sure that it is serialized against | 671 // Runs on FILE thread to make sure that it is serialized against |
666 // {Start|Stop}HandlerThread and to allow calling pthread_join. | 672 // {Start|Stop}HandlerThread and to allow calling pthread_join. |
667 void DevToolsHttpHandlerImpl::StopHandlerThread() { | 673 void DevToolsHttpHandlerImpl::StopHandlerThread() { |
668 if (!thread_->message_loop()) | 674 if (!thread_->message_loop()) |
669 return; | 675 return; |
670 thread_->message_loop()->PostTask( | 676 thread_->message_loop()->PostTask( |
671 FROM_HERE, | 677 FROM_HERE, |
672 base::Bind(&DevToolsHttpHandlerImpl::Teardown, this)); | 678 base::Bind(&DevToolsHttpHandlerImpl::Teardown, this)); |
(...skipping 18 matching lines...) Expand all Loading... |
691 std::string json_message; | 697 std::string json_message; |
692 scoped_ptr<base::Value> message_object(new base::StringValue(message)); | 698 scoped_ptr<base::Value> message_object(new base::StringValue(message)); |
693 base::JSONWriter::Write(message_object.get(), &json_message); | 699 base::JSONWriter::Write(message_object.get(), &json_message); |
694 | 700 |
695 net::HttpServerResponseInfo response(status_code); | 701 net::HttpServerResponseInfo response(status_code); |
696 response.SetBody(json_value + message, "application/json; charset=UTF-8"); | 702 response.SetBody(json_value + message, "application/json; charset=UTF-8"); |
697 | 703 |
698 thread_->message_loop()->PostTask( | 704 thread_->message_loop()->PostTask( |
699 FROM_HERE, | 705 FROM_HERE, |
700 base::Bind(&net::HttpServer::SendResponse, | 706 base::Bind(&net::HttpServer::SendResponse, |
701 server_.get(), | 707 server_->GetWeakPtr(), |
702 connection_id, | 708 connection_id, |
703 response)); | 709 response)); |
704 } | 710 } |
705 | 711 |
706 void DevToolsHttpHandlerImpl::Send200(int connection_id, | 712 void DevToolsHttpHandlerImpl::Send200(int connection_id, |
707 const std::string& data, | 713 const std::string& data, |
708 const std::string& mime_type) { | 714 const std::string& mime_type) { |
709 if (!thread_) | 715 if (!thread_) |
710 return; | 716 return; |
711 thread_->message_loop()->PostTask( | 717 thread_->message_loop()->PostTask( |
712 FROM_HERE, | 718 FROM_HERE, |
713 base::Bind(&net::HttpServer::Send200, | 719 base::Bind(&net::HttpServer::Send200, |
714 server_.get(), | 720 server_->GetWeakPtr(), |
715 connection_id, | 721 connection_id, |
716 data, | 722 data, |
717 mime_type)); | 723 mime_type)); |
718 } | 724 } |
719 | 725 |
720 void DevToolsHttpHandlerImpl::Send404(int connection_id) { | 726 void DevToolsHttpHandlerImpl::Send404(int connection_id) { |
721 if (!thread_) | 727 if (!thread_) |
722 return; | 728 return; |
723 thread_->message_loop()->PostTask( | 729 thread_->message_loop()->PostTask( |
724 FROM_HERE, | 730 FROM_HERE, |
725 base::Bind(&net::HttpServer::Send404, server_.get(), connection_id)); | 731 base::Bind(&net::HttpServer::Send404, |
| 732 server_->GetWeakPtr(), |
| 733 connection_id)); |
726 } | 734 } |
727 | 735 |
728 void DevToolsHttpHandlerImpl::Send500(int connection_id, | 736 void DevToolsHttpHandlerImpl::Send500(int connection_id, |
729 const std::string& message) { | 737 const std::string& message) { |
730 if (!thread_) | 738 if (!thread_) |
731 return; | 739 return; |
732 thread_->message_loop()->PostTask( | 740 thread_->message_loop()->PostTask( |
733 FROM_HERE, | 741 FROM_HERE, |
734 base::Bind(&net::HttpServer::Send500, server_.get(), connection_id, | 742 base::Bind(&net::HttpServer::Send500, |
| 743 server_->GetWeakPtr(), |
| 744 connection_id, |
735 message)); | 745 message)); |
736 } | 746 } |
737 | 747 |
738 void DevToolsHttpHandlerImpl::AcceptWebSocket( | 748 void DevToolsHttpHandlerImpl::AcceptWebSocket( |
739 int connection_id, | 749 int connection_id, |
740 const net::HttpServerRequestInfo& request) { | 750 const net::HttpServerRequestInfo& request) { |
741 if (!thread_) | 751 if (!thread_) |
742 return; | 752 return; |
743 thread_->message_loop()->PostTask( | 753 thread_->message_loop()->PostTask( |
744 FROM_HERE, | 754 FROM_HERE, |
745 base::Bind(&net::HttpServer::AcceptWebSocket, server_.get(), | 755 base::Bind(&net::HttpServer::SetSendBufferSize, |
746 connection_id, request)); | 756 server_->GetWeakPtr(), |
| 757 connection_id, |
| 758 kSendBufferSizeForDevToolsWebSocket)); |
| 759 thread_->message_loop()->PostTask( |
| 760 FROM_HERE, |
| 761 base::Bind(&net::HttpServer::AcceptWebSocket, |
| 762 server_->GetWeakPtr(), |
| 763 connection_id, |
| 764 request)); |
747 } | 765 } |
748 | 766 |
749 base::DictionaryValue* DevToolsHttpHandlerImpl::SerializeTarget( | 767 base::DictionaryValue* DevToolsHttpHandlerImpl::SerializeTarget( |
750 const DevToolsTarget& target, | 768 const DevToolsTarget& target, |
751 const std::string& host) { | 769 const std::string& host) { |
752 base::DictionaryValue* dictionary = new base::DictionaryValue; | 770 base::DictionaryValue* dictionary = new base::DictionaryValue; |
753 | 771 |
754 std::string id = target.GetId(); | 772 std::string id = target.GetId(); |
755 dictionary->SetString(kTargetIdField, id); | 773 dictionary->SetString(kTargetIdField, id); |
756 dictionary->SetString(kTargetTypeField, target.GetType()); | 774 dictionary->SetString(kTargetTypeField, target.GetType()); |
(...skipping 23 matching lines...) Expand all Loading... |
780 id.c_str(), | 798 id.c_str(), |
781 host); | 799 host); |
782 dictionary->SetString( | 800 dictionary->SetString( |
783 kTargetDevtoolsFrontendUrlField, devtools_frontend_url); | 801 kTargetDevtoolsFrontendUrlField, devtools_frontend_url); |
784 } | 802 } |
785 | 803 |
786 return dictionary; | 804 return dictionary; |
787 } | 805 } |
788 | 806 |
789 } // namespace content | 807 } // namespace content |
OLD | NEW |