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 <stddef.h> | 5 #include <stddef.h> |
6 #include <stdint.h> | 6 #include <stdint.h> |
7 | 7 |
8 #include <algorithm> | 8 #include <algorithm> |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/compiler_specific.h" | 12 #include "base/compiler_specific.h" |
13 #include "base/files/file_util.h" | 13 #include "base/files/file_util.h" |
14 #include "base/json/json_writer.h" | 14 #include "base/json/json_writer.h" |
15 #include "base/location.h" | 15 #include "base/location.h" |
16 #include "base/logging.h" | 16 #include "base/logging.h" |
17 #include "base/single_thread_task_runner.h" | 17 #include "base/single_thread_task_runner.h" |
18 #include "base/stl_util.h" | 18 #include "base/stl_util.h" |
19 #include "base/strings/string_number_conversions.h" | 19 #include "base/strings/string_number_conversions.h" |
20 #include "base/strings/string_util.h" | 20 #include "base/strings/string_util.h" |
21 #include "base/strings/stringprintf.h" | 21 #include "base/strings/stringprintf.h" |
22 #include "base/threading/thread.h" | 22 #include "base/threading/thread.h" |
23 #include "base/values.h" | 23 #include "base/values.h" |
24 #include "build/build_config.h" | 24 #include "build/build_config.h" |
25 #include "components/devtools_http_handler/devtools_http_handler.h" | 25 #include "content/browser/devtools/devtools_http_handler.h" |
26 #include "components/devtools_http_handler/devtools_http_handler_delegate.h" | 26 #include "content/browser/devtools/devtools_manager.h" |
27 #include "content/public/browser/browser_thread.h" | 27 #include "content/public/browser/browser_thread.h" |
28 #include "content/public/browser/devtools_external_agent_proxy_delegate.h" | 28 #include "content/public/browser/devtools_external_agent_proxy_delegate.h" |
29 #include "content/public/browser/devtools_manager_delegate.h" | 29 #include "content/public/browser/devtools_manager_delegate.h" |
30 #include "content/public/browser/devtools_socket_factory.h" | 30 #include "content/public/browser/devtools_socket_factory.h" |
31 #include "content/public/common/url_constants.h" | 31 #include "content/public/common/url_constants.h" |
32 #include "content/public/common/user_agent.h" | 32 #include "content/public/common/user_agent.h" |
33 #include "net/base/escape.h" | 33 #include "net/base/escape.h" |
34 #include "net/base/io_buffer.h" | 34 #include "net/base/io_buffer.h" |
35 #include "net/base/ip_endpoint.h" | 35 #include "net/base/ip_endpoint.h" |
36 #include "net/base/net_errors.h" | 36 #include "net/base/net_errors.h" |
37 #include "net/server/http_server.h" | 37 #include "net/server/http_server.h" |
38 #include "net/server/http_server_request_info.h" | 38 #include "net/server/http_server_request_info.h" |
39 #include "net/server/http_server_response_info.h" | 39 #include "net/server/http_server_response_info.h" |
40 #include "net/socket/server_socket.h" | 40 #include "net/socket/server_socket.h" |
41 | 41 |
42 #if defined(OS_ANDROID) | 42 #if defined(OS_ANDROID) |
43 #include "base/android/build_info.h" | 43 #include "base/android/build_info.h" |
44 #endif | 44 #endif |
45 | 45 |
46 using content::BrowserThread; | 46 namespace content { |
47 using content::DevToolsAgentHost; | |
48 using content::DevToolsAgentHostClient; | |
49 | |
50 namespace devtools_http_handler { | |
51 | 47 |
52 namespace { | 48 namespace { |
53 | 49 |
54 const base::FilePath::CharType kDevToolsActivePortFileName[] = | 50 const base::FilePath::CharType kDevToolsActivePortFileName[] = |
55 FILE_PATH_LITERAL("DevToolsActivePort"); | 51 FILE_PATH_LITERAL("DevToolsActivePort"); |
56 | 52 |
57 const char kDevToolsHandlerThreadName[] = "Chrome_DevToolsHandlerThread"; | 53 const char kDevToolsHandlerThreadName[] = "Chrome_DevToolsHandlerThread"; |
58 | 54 |
59 const char kPageUrlPrefix[] = "/devtools/page/"; | 55 const char kPageUrlPrefix[] = "/devtools/page/"; |
60 | 56 |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
164 } | 160 } |
165 | 161 |
166 void ServerWrapper::Close(int connection_id) { | 162 void ServerWrapper::Close(int connection_id) { |
167 server_->Close(connection_id); | 163 server_->Close(connection_id); |
168 } | 164 } |
169 | 165 |
170 // Thread and ServerWrapper lifetime management ------------------------------ | 166 // Thread and ServerWrapper lifetime management ------------------------------ |
171 | 167 |
172 void TerminateOnUI(base::Thread* thread, | 168 void TerminateOnUI(base::Thread* thread, |
173 ServerWrapper* server_wrapper, | 169 ServerWrapper* server_wrapper, |
174 content::DevToolsSocketFactory* socket_factory) { | 170 DevToolsSocketFactory* socket_factory) { |
175 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 171 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
176 if (server_wrapper) { | 172 if (server_wrapper) { |
177 DCHECK(thread); | 173 DCHECK(thread); |
178 thread->task_runner()->DeleteSoon(FROM_HERE, server_wrapper); | 174 thread->task_runner()->DeleteSoon(FROM_HERE, server_wrapper); |
179 } | 175 } |
180 if (socket_factory) { | 176 if (socket_factory) { |
181 DCHECK(thread); | 177 DCHECK(thread); |
182 thread->task_runner()->DeleteSoon(FROM_HERE, socket_factory); | 178 thread->task_runner()->DeleteSoon(FROM_HERE, socket_factory); |
183 } | 179 } |
184 if (thread) { | 180 if (thread) { |
185 BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, thread); | 181 BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, thread); |
186 } | 182 } |
187 } | 183 } |
188 | 184 |
189 void ServerStartedOnUI(base::WeakPtr<DevToolsHttpHandler> handler, | 185 void ServerStartedOnUI(base::WeakPtr<DevToolsHttpHandler> handler, |
190 base::Thread* thread, | 186 base::Thread* thread, |
191 ServerWrapper* server_wrapper, | 187 ServerWrapper* server_wrapper, |
192 content::DevToolsSocketFactory* socket_factory, | 188 DevToolsSocketFactory* socket_factory, |
193 std::unique_ptr<net::IPEndPoint> ip_address) { | 189 std::unique_ptr<net::IPEndPoint> ip_address) { |
194 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 190 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
195 if (handler && thread && server_wrapper) { | 191 if (handler && thread && server_wrapper) { |
196 handler->ServerStarted(thread, server_wrapper, socket_factory, | 192 handler->ServerStarted(thread, server_wrapper, socket_factory, |
197 std::move(ip_address)); | 193 std::move(ip_address)); |
198 } else { | 194 } else { |
199 TerminateOnUI(thread, server_wrapper, socket_factory); | 195 TerminateOnUI(thread, server_wrapper, socket_factory); |
200 } | 196 } |
201 } | 197 } |
202 | 198 |
203 void StartServerOnHandlerThread( | 199 void StartServerOnHandlerThread( |
204 base::WeakPtr<DevToolsHttpHandler> handler, | 200 base::WeakPtr<DevToolsHttpHandler> handler, |
205 base::Thread* thread, | 201 base::Thread* thread, |
206 content::DevToolsSocketFactory* socket_factory, | 202 DevToolsSocketFactory* socket_factory, |
207 const base::FilePath& output_directory, | 203 const base::FilePath& output_directory, |
208 const base::FilePath& frontend_dir, | 204 const base::FilePath& frontend_dir, |
209 bool bundles_resources) { | 205 bool bundles_resources) { |
210 DCHECK(thread->task_runner()->BelongsToCurrentThread()); | 206 DCHECK(thread->task_runner()->BelongsToCurrentThread()); |
211 ServerWrapper* server_wrapper = nullptr; | 207 ServerWrapper* server_wrapper = nullptr; |
212 std::unique_ptr<net::ServerSocket> server_socket = | 208 std::unique_ptr<net::ServerSocket> server_socket = |
213 socket_factory->CreateForHttpServer(); | 209 socket_factory->CreateForHttpServer(); |
214 std::unique_ptr<net::IPEndPoint> ip_address(new net::IPEndPoint); | 210 std::unique_ptr<net::IPEndPoint> ip_address(new net::IPEndPoint); |
215 if (server_socket) { | 211 if (server_socket) { |
216 server_wrapper = new ServerWrapper(handler, std::move(server_socket), | 212 server_wrapper = new ServerWrapper(handler, std::move(server_socket), |
(...skipping 11 matching lines...) Expand all Loading... |
228 base::Bind(&ServerStartedOnUI, | 224 base::Bind(&ServerStartedOnUI, |
229 handler, | 225 handler, |
230 thread, | 226 thread, |
231 server_wrapper, | 227 server_wrapper, |
232 socket_factory, | 228 socket_factory, |
233 base::Passed(&ip_address))); | 229 base::Passed(&ip_address))); |
234 } | 230 } |
235 | 231 |
236 void StartServerOnFile( | 232 void StartServerOnFile( |
237 base::WeakPtr<DevToolsHttpHandler> handler, | 233 base::WeakPtr<DevToolsHttpHandler> handler, |
238 content::DevToolsSocketFactory* socket_factory, | 234 DevToolsSocketFactory* socket_factory, |
239 const base::FilePath& output_directory, | 235 const base::FilePath& output_directory, |
240 const base::FilePath& frontend_dir, | 236 const base::FilePath& frontend_dir, |
241 bool bundles_resources) { | 237 bool bundles_resources) { |
242 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 238 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
243 std::unique_ptr<base::Thread> thread( | 239 std::unique_ptr<base::Thread> thread( |
244 new base::Thread(kDevToolsHandlerThreadName)); | 240 new base::Thread(kDevToolsHandlerThreadName)); |
245 base::Thread::Options options; | 241 base::Thread::Options options; |
246 options.message_loop_type = base::MessageLoop::TYPE_IO; | 242 options.message_loop_type = base::MessageLoop::TYPE_IO; |
247 if (thread->StartWithOptions(options)) { | 243 if (thread->StartWithOptions(options)) { |
248 base::MessageLoop* message_loop = thread->message_loop(); | 244 base::MessageLoop* message_loop = thread->message_loop(); |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
519 net::HTTP_NOT_FOUND, | 515 net::HTTP_NOT_FOUND, |
520 NULL, | 516 NULL, |
521 "Malformed query: " + info.path); | 517 "Malformed query: " + info.path); |
522 return; | 518 return; |
523 } | 519 } |
524 | 520 |
525 if (command == "version") { | 521 if (command == "version") { |
526 base::DictionaryValue version; | 522 base::DictionaryValue version; |
527 version.SetString("Protocol-Version", | 523 version.SetString("Protocol-Version", |
528 DevToolsAgentHost::GetProtocolVersion().c_str()); | 524 DevToolsAgentHost::GetProtocolVersion().c_str()); |
529 version.SetString("WebKit-Version", content::GetWebKitVersion()); | 525 version.SetString("WebKit-Version", GetWebKitVersion()); |
530 version.SetString("Browser", product_name_); | 526 version.SetString("Browser", product_name_); |
531 version.SetString("User-Agent", user_agent_); | 527 version.SetString("User-Agent", user_agent_); |
532 #if defined(OS_ANDROID) | 528 #if defined(OS_ANDROID) |
533 version.SetString("Android-Package", | 529 version.SetString("Android-Package", |
534 base::android::BuildInfo::GetInstance()->package_name()); | 530 base::android::BuildInfo::GetInstance()->package_name()); |
535 #endif | 531 #endif |
536 SendJson(connection_id, net::HTTP_OK, &version, std::string()); | 532 SendJson(connection_id, net::HTTP_OK, &version, std::string()); |
537 return; | 533 return; |
538 } | 534 } |
539 | 535 |
540 if (command == "list") { | 536 if (command == "list") { |
541 std::string host = info.headers["host"]; | 537 std::string host = info.headers["host"]; |
542 DevToolsAgentHost::List agent_hosts = | 538 DevToolsAgentHost::List agent_hosts = |
543 content::DevToolsAgentHost::DiscoverAllHosts(); | 539 DevToolsAgentHost::DiscoverAllHosts(); |
544 std::sort(agent_hosts.begin(), agent_hosts.end(), TimeComparator); | 540 std::sort(agent_hosts.begin(), agent_hosts.end(), TimeComparator); |
545 agent_host_map_.clear(); | 541 agent_host_map_.clear(); |
546 base::ListValue list_value; | 542 base::ListValue list_value; |
547 for (auto& agent_host : agent_hosts) { | 543 for (auto& agent_host : agent_hosts) { |
548 agent_host_map_[agent_host->GetId()] = agent_host; | 544 agent_host_map_[agent_host->GetId()] = agent_host; |
549 list_value.Append(SerializeDescriptor(agent_host, host)); | 545 list_value.Append(SerializeDescriptor(agent_host, host)); |
550 } | 546 } |
551 SendJson(connection_id, net::HTTP_OK, &list_value, std::string()); | 547 SendJson(connection_id, net::HTTP_OK, &list_value, std::string()); |
552 return; | 548 return; |
553 } | 549 } |
554 | 550 |
555 if (command == "new") { | 551 if (command == "new") { |
556 GURL url(net::UnescapeURLComponent( | 552 GURL url(net::UnescapeURLComponent( |
557 query, net::UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS | | 553 query, net::UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS | |
558 net::UnescapeRule::PATH_SEPARATORS)); | 554 net::UnescapeRule::PATH_SEPARATORS)); |
559 if (!url.is_valid()) | 555 if (!url.is_valid()) |
560 url = GURL(url::kAboutBlankURL); | 556 url = GURL(url::kAboutBlankURL); |
561 scoped_refptr<DevToolsAgentHost> agent_host = nullptr; | 557 scoped_refptr<DevToolsAgentHost> agent_host = nullptr; |
562 content::DevToolsManagerDelegate* delegate = | 558 agent_host = delegate_->CreateNewTarget(url); |
563 DevToolsAgentHost::GetDevToolsManagerDelegate(); | |
564 if (delegate) | |
565 agent_host = delegate->CreateNewTarget(url); | |
566 if (!agent_host) { | 559 if (!agent_host) { |
567 SendJson(connection_id, | 560 SendJson(connection_id, |
568 net::HTTP_INTERNAL_SERVER_ERROR, | 561 net::HTTP_INTERNAL_SERVER_ERROR, |
569 NULL, | 562 NULL, |
570 "Could not create new page"); | 563 "Could not create new page"); |
571 return; | 564 return; |
572 } | 565 } |
573 std::string host = info.headers["host"]; | 566 std::string host = info.headers["host"]; |
574 std::unique_ptr<base::DictionaryValue> dictionary( | 567 std::unique_ptr<base::DictionaryValue> dictionary( |
575 SerializeDescriptor(agent_host, host)); | 568 SerializeDescriptor(agent_host, host)); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
643 const net::HttpServerRequestInfo& request) { | 636 const net::HttpServerRequestInfo& request) { |
644 if (!thread_) | 637 if (!thread_) |
645 return; | 638 return; |
646 | 639 |
647 std::string browser_prefix = "/devtools/browser"; | 640 std::string browser_prefix = "/devtools/browser"; |
648 if (base::StartsWith(request.path, browser_prefix, | 641 if (base::StartsWith(request.path, browser_prefix, |
649 base::CompareCase::SENSITIVE)) { | 642 base::CompareCase::SENSITIVE)) { |
650 scoped_refptr<DevToolsAgentHost> browser_agent = | 643 scoped_refptr<DevToolsAgentHost> browser_agent = |
651 DevToolsAgentHost::CreateForBrowser( | 644 DevToolsAgentHost::CreateForBrowser( |
652 thread_->task_runner(), | 645 thread_->task_runner(), |
653 base::Bind(&content::DevToolsSocketFactory::CreateForTethering, | 646 base::Bind(&DevToolsSocketFactory::CreateForTethering, |
654 base::Unretained(socket_factory_))); | 647 base::Unretained(socket_factory_))); |
655 connection_to_client_[connection_id] = new DevToolsAgentHostClientImpl( | 648 connection_to_client_[connection_id] = new DevToolsAgentHostClientImpl( |
656 thread_->message_loop(), server_wrapper_, connection_id, browser_agent); | 649 thread_->message_loop(), server_wrapper_, connection_id, browser_agent); |
657 AcceptWebSocket(connection_id, request); | 650 AcceptWebSocket(connection_id, request); |
658 return; | 651 return; |
659 } | 652 } |
660 | 653 |
661 if (!base::StartsWith(request.path, kPageUrlPrefix, | 654 if (!base::StartsWith(request.path, kPageUrlPrefix, |
662 base::CompareCase::SENSITIVE)) { | 655 base::CompareCase::SENSITIVE)) { |
663 Send404(connection_id); | 656 Send404(connection_id); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
696 void DevToolsHttpHandler::OnClose(int connection_id) { | 689 void DevToolsHttpHandler::OnClose(int connection_id) { |
697 ConnectionToClientMap::iterator it = | 690 ConnectionToClientMap::iterator it = |
698 connection_to_client_.find(connection_id); | 691 connection_to_client_.find(connection_id); |
699 if (it != connection_to_client_.end()) { | 692 if (it != connection_to_client_.end()) { |
700 delete it->second; | 693 delete it->second; |
701 connection_to_client_.erase(connection_id); | 694 connection_to_client_.erase(connection_id); |
702 } | 695 } |
703 } | 696 } |
704 | 697 |
705 DevToolsHttpHandler::DevToolsHttpHandler( | 698 DevToolsHttpHandler::DevToolsHttpHandler( |
706 std::unique_ptr<content::DevToolsSocketFactory> socket_factory, | 699 DevToolsManagerDelegate* delegate, |
| 700 std::unique_ptr<DevToolsSocketFactory> socket_factory, |
707 const std::string& frontend_url, | 701 const std::string& frontend_url, |
708 DevToolsHttpHandlerDelegate* delegate, | |
709 const base::FilePath& output_directory, | 702 const base::FilePath& output_directory, |
710 const base::FilePath& debug_frontend_dir, | 703 const base::FilePath& debug_frontend_dir, |
711 const std::string& product_name, | 704 const std::string& product_name, |
712 const std::string& user_agent) | 705 const std::string& user_agent) |
713 : thread_(nullptr), | 706 : thread_(nullptr), |
714 frontend_url_(frontend_url), | 707 frontend_url_(frontend_url), |
715 product_name_(product_name), | 708 product_name_(product_name), |
716 user_agent_(user_agent), | 709 user_agent_(user_agent), |
717 server_wrapper_(nullptr), | 710 server_wrapper_(nullptr), |
718 delegate_(delegate), | 711 delegate_(delegate), |
719 socket_factory_(nullptr), | 712 socket_factory_(nullptr), |
720 weak_factory_(this) { | 713 weak_factory_(this) { |
721 bool bundles_resources = frontend_url_.empty(); | 714 bool bundles_resources = frontend_url_.empty(); |
722 if (frontend_url_.empty()) | 715 if (frontend_url_.empty()) |
723 frontend_url_ = "/devtools/inspector.html"; | 716 frontend_url_ = "/devtools/inspector.html"; |
724 | 717 |
725 BrowserThread::PostTask( | 718 BrowserThread::PostTask( |
726 BrowserThread::FILE, FROM_HERE, | 719 BrowserThread::FILE, FROM_HERE, |
727 base::Bind(&StartServerOnFile, | 720 base::Bind(&StartServerOnFile, |
728 weak_factory_.GetWeakPtr(), | 721 weak_factory_.GetWeakPtr(), |
729 socket_factory.release(), | 722 socket_factory.release(), |
730 output_directory, | 723 output_directory, |
731 debug_frontend_dir, | 724 debug_frontend_dir, |
732 bundles_resources)); | 725 bundles_resources)); |
733 } | 726 } |
734 | 727 |
735 void DevToolsHttpHandler::ServerStarted( | 728 void DevToolsHttpHandler::ServerStarted( |
736 base::Thread* thread, | 729 base::Thread* thread, |
737 ServerWrapper* server_wrapper, | 730 ServerWrapper* server_wrapper, |
738 content::DevToolsSocketFactory* socket_factory, | 731 DevToolsSocketFactory* socket_factory, |
739 std::unique_ptr<net::IPEndPoint> ip_address) { | 732 std::unique_ptr<net::IPEndPoint> ip_address) { |
740 thread_ = thread; | 733 thread_ = thread; |
741 server_wrapper_ = server_wrapper; | 734 server_wrapper_ = server_wrapper; |
742 socket_factory_ = socket_factory; | 735 socket_factory_ = socket_factory; |
743 server_ip_address_.swap(ip_address); | 736 server_ip_address_.swap(ip_address); |
744 } | 737 } |
745 | 738 |
746 void ServerWrapper::WriteActivePortToUserProfile( | 739 void ServerWrapper::WriteActivePortToUserProfile( |
747 const base::FilePath& output_directory) { | 740 const base::FilePath& output_directory) { |
748 DCHECK(!output_directory.empty()); | 741 DCHECK(!output_directory.empty()); |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
858 std::string devtools_frontend_url = GetFrontendURLInternal( | 851 std::string devtools_frontend_url = GetFrontendURLInternal( |
859 id.c_str(), | 852 id.c_str(), |
860 host); | 853 host); |
861 dictionary->SetString( | 854 dictionary->SetString( |
862 kTargetDevtoolsFrontendUrlField, devtools_frontend_url); | 855 kTargetDevtoolsFrontendUrlField, devtools_frontend_url); |
863 } | 856 } |
864 | 857 |
865 return dictionary; | 858 return dictionary; |
866 } | 859 } |
867 | 860 |
868 } // namespace devtools_http_handler | 861 } // namespace content |
OLD | NEW |