blob: db7bd746debc2adb5b5a09ace4584d117497e682 [file] [log] [blame]
[email protected]de7d61ff2013-08-20 11:30:411// Copyright 2013 The Chromium Authors. All rights reserved.
[email protected]ee75b8992012-01-27 07:53:572// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
vkuzkokovcbabd582014-11-06 13:53:545#include "content/shell/browser/shell_devtools_manager_delegate.h"
[email protected]ee75b8992012-01-27 07:53:576
avi66a07722015-12-25 23:38:127#include <stdint.h>
8
[email protected]90e6c5412013-04-16 22:45:259#include <vector>
10
pfeldmanf7c18d0242016-09-08 19:54:2611#include "base/atomicops.h"
[email protected]ed6635e2012-10-27 00:44:0912#include "base/bind.h"
[email protected]90e6c5412013-04-16 22:45:2513#include "base/command_line.h"
[email protected]0e60fce2014-06-04 22:27:2014#include "base/files/file_path.h"
avi66a07722015-12-25 23:38:1215#include "base/macros.h"
dcheng6003e0b2016-04-09 18:42:3416#include "base/memory/ptr_util.h"
[email protected]90e6c5412013-04-16 22:45:2517#include "base/strings/string_number_conversions.h"
[email protected]8dffd2c2013-12-02 14:14:3818#include "base/strings/stringprintf.h"
[email protected]852b34ba2013-10-03 16:29:0619#include "base/strings/utf_string_conversions.h"
avi66a07722015-12-25 23:38:1220#include "build/build_config.h"
yzshen6051dfd32015-10-20 19:23:2521#include "content/public/browser/browser_context.h"
[email protected]852b34ba2013-10-03 16:29:0622#include "content/public/browser/devtools_agent_host.h"
pfeldmanf1a16942016-09-02 21:28:0023#include "content/public/browser/devtools_socket_factory.h"
[email protected]852b34ba2013-10-03 16:29:0624#include "content/public/browser/favicon_status.h"
25#include "content/public/browser/navigation_entry.h"
26#include "content/public/browser/render_view_host.h"
[email protected]eb040992012-10-10 16:56:0027#include "content/public/browser/web_contents.h"
[email protected]90e6c5412013-04-16 22:45:2528#include "content/public/common/content_switches.h"
[email protected]eb040992012-10-10 16:56:0029#include "content/public/common/url_constants.h"
[email protected]efd2c3f2014-03-11 09:57:2530#include "content/public/common/user_agent.h"
[email protected]de7d61ff2013-08-20 11:30:4131#include "content/shell/browser/shell.h"
dgozman102fee92015-04-20 15:45:4632#include "content/shell/common/shell_content_client.h"
thakisda47dac2017-02-27 14:35:3033#include "content/shell/grit/shell_resources.h"
vkuzkokov79426762015-01-13 08:03:0034#include "net/base/net_errors.h"
mikecironef22f9812016-10-04 03:40:1935#include "net/log/net_log_source.h"
byungchul38c3ae72014-08-25 23:27:4636#include "net/socket/tcp_server_socket.h"
[email protected]ee75b8992012-01-27 07:53:5737#include "ui/base/resource/resource_bundle.h"
38
chenwilliame88d8362017-03-21 02:34:3039#if !defined(OS_ANDROID)
40#include "content/public/browser/devtools_frontend_host.h"
41#endif
42
[email protected]ed6635e2012-10-27 00:44:0943#if defined(OS_ANDROID)
44#include "content/public/browser/android/devtools_auth.h"
byungchul38c3ae72014-08-25 23:27:4645#include "net/socket/unix_domain_server_socket_posix.h"
[email protected]90e6c5412013-04-16 22:45:2546#endif
[email protected]ed6635e2012-10-27 00:44:0947
vkuzkokovcbabd582014-11-06 13:53:5448namespace content {
[email protected]852b34ba2013-10-03 16:29:0649
[email protected]ed6635e2012-10-27 00:44:0950namespace {
[email protected]90e6c5412013-04-16 22:45:2551
[email protected]8dffd2c2013-12-02 14:14:3852#if defined(OS_ANDROID)
53const char kFrontEndURL[] =
dgozmana1409c42014-11-19 16:06:1254 "http://chrome-devtools-frontend.appspot.com/serve_rev/%s/inspector.html";
[email protected]8dffd2c2013-12-02 14:14:3855#endif
[email protected]852b34ba2013-10-03 16:29:0656
vkuzkokov79426762015-01-13 08:03:0057const int kBackLog = 10;
58
pfeldmanf7c18d0242016-09-08 19:54:2659base::subtle::Atomic32 g_last_used_port;
60
byungchul38c3ae72014-08-25 23:27:4661#if defined(OS_ANDROID)
pfeldmanf1a16942016-09-02 21:28:0062class UnixDomainServerSocketFactory : public content::DevToolsSocketFactory {
byungchul38c3ae72014-08-25 23:27:4663 public:
64 explicit UnixDomainServerSocketFactory(const std::string& socket_name)
vkuzkokov79426762015-01-13 08:03:0065 : socket_name_(socket_name) {}
byungchul38c3ae72014-08-25 23:27:4666
67 private:
pfeldmanf1a16942016-09-02 21:28:0068 // content::DevToolsSocketFactory.
dcheng6003e0b2016-04-09 18:42:3469 std::unique_ptr<net::ServerSocket> CreateForHttpServer() override {
70 std::unique_ptr<net::UnixDomainServerSocket> socket(
tfarinaa7b245d2016-02-02 02:03:4971 new net::UnixDomainServerSocket(base::Bind(&CanUserConnectToDevTools),
72 true /* use_abstract_namespace */));
73 if (socket->BindAndListen(socket_name_, kBackLog) != net::OK)
dcheng6003e0b2016-04-09 18:42:3474 return std::unique_ptr<net::ServerSocket>();
vkuzkokov79426762015-01-13 08:03:0075
tfarinaa7b245d2016-02-02 02:03:4976 return std::move(socket);
byungchul38c3ae72014-08-25 23:27:4677 }
78
pfeldmanf1a16942016-09-02 21:28:0079 std::unique_ptr<net::ServerSocket> CreateForTethering(
80 std::string* out_name) override {
81 return nullptr;
82 }
83
vkuzkokov79426762015-01-13 08:03:0084 std::string socket_name_;
85
byungchul38c3ae72014-08-25 23:27:4686 DISALLOW_COPY_AND_ASSIGN(UnixDomainServerSocketFactory);
87};
88#else
pfeldmanf1a16942016-09-02 21:28:0089class TCPServerSocketFactory : public content::DevToolsSocketFactory {
byungchul38c3ae72014-08-25 23:27:4690 public:
avi66a07722015-12-25 23:38:1291 TCPServerSocketFactory(const std::string& address, uint16_t port)
92 : address_(address), port_(port) {}
byungchul38c3ae72014-08-25 23:27:4693
94 private:
pfeldmanf1a16942016-09-02 21:28:0095 // content::DevToolsSocketFactory.
dcheng6003e0b2016-04-09 18:42:3496 std::unique_ptr<net::ServerSocket> CreateForHttpServer() override {
97 std::unique_ptr<net::ServerSocket> socket(
mikecironef22f9812016-10-04 03:40:1998 new net::TCPServerSocket(nullptr, net::NetLogSource()));
vkuzkokov79426762015-01-13 08:03:0099 if (socket->ListenWithAddressAndPort(address_, port_, kBackLog) != net::OK)
dcheng6003e0b2016-04-09 18:42:34100 return std::unique_ptr<net::ServerSocket>();
vkuzkokov79426762015-01-13 08:03:00101
pfeldmanf7c18d0242016-09-08 19:54:26102 net::IPEndPoint endpoint;
103 if (socket->GetLocalAddress(&endpoint) == net::OK)
104 base::subtle::NoBarrier_Store(&g_last_used_port, endpoint.port());
105
vkuzkokov79426762015-01-13 08:03:00106 return socket;
byungchul38c3ae72014-08-25 23:27:46107 }
108
pfeldmanf1a16942016-09-02 21:28:00109 std::unique_ptr<net::ServerSocket> CreateForTethering(
110 std::string* out_name) override {
111 return nullptr;
112 }
113
vkuzkokov79426762015-01-13 08:03:00114 std::string address_;
avi66a07722015-12-25 23:38:12115 uint16_t port_;
vkuzkokov79426762015-01-13 08:03:00116
byungchul38c3ae72014-08-25 23:27:46117 DISALLOW_COPY_AND_ASSIGN(TCPServerSocketFactory);
118};
119#endif
120
pfeldmanf1a16942016-09-02 21:28:00121std::unique_ptr<content::DevToolsSocketFactory> CreateSocketFactory() {
avi83883c82014-12-23 00:08:49122 const base::CommandLine& command_line =
123 *base::CommandLine::ForCurrentProcess();
[email protected]90e6c5412013-04-16 22:45:25124#if defined(OS_ANDROID)
125 std::string socket_name = "content_shell_devtools_remote";
126 if (command_line.HasSwitch(switches::kRemoteDebuggingSocketName)) {
127 socket_name = command_line.GetSwitchValueASCII(
128 switches::kRemoteDebuggingSocketName);
129 }
pfeldmanf1a16942016-09-02 21:28:00130 return std::unique_ptr<content::DevToolsSocketFactory>(
byungchul38c3ae72014-08-25 23:27:46131 new UnixDomainServerSocketFactory(socket_name));
[email protected]90e6c5412013-04-16 22:45:25132#else
133 // See if the user specified a port on the command line (useful for
134 // automation). If not, use an ephemeral port by specifying 0.
avi66a07722015-12-25 23:38:12135 uint16_t port = 0;
[email protected]90e6c5412013-04-16 22:45:25136 if (command_line.HasSwitch(switches::kRemoteDebuggingPort)) {
137 int temp_port;
138 std::string port_str =
139 command_line.GetSwitchValueASCII(switches::kRemoteDebuggingPort);
140 if (base::StringToInt(port_str, &temp_port) &&
yzshen6051dfd32015-10-20 19:23:25141 temp_port >= 0 && temp_port < 65535) {
avi66a07722015-12-25 23:38:12142 port = static_cast<uint16_t>(temp_port);
[email protected]90e6c5412013-04-16 22:45:25143 } else {
144 DLOG(WARNING) << "Invalid http debugger port number " << temp_port;
145 }
146 }
pfeldmanf1a16942016-09-02 21:28:00147 return std::unique_ptr<content::DevToolsSocketFactory>(
vkuzkokov79426762015-01-13 08:03:00148 new TCPServerSocketFactory("127.0.0.1", port));
[email protected]ed6635e2012-10-27 00:44:09149#endif
[email protected]90e6c5412013-04-16 22:45:25150}
[email protected]852b34ba2013-10-03 16:29:06151
pfeldman10628762016-09-08 07:59:26152} // namespace
vkuzkokovcbabd582014-11-06 13:53:54153
dgozman252e18d2014-09-22 12:40:06154// ShellDevToolsManagerDelegate ----------------------------------------------
155
vkuzkokovcbabd582014-11-06 13:53:54156// static
pfeldmanf7c18d0242016-09-08 19:54:26157int ShellDevToolsManagerDelegate::GetHttpHandlerPort() {
158 return base::subtle::NoBarrier_Load(&g_last_used_port);
159}
160
161// static
pfeldman10628762016-09-08 07:59:26162void ShellDevToolsManagerDelegate::StartHttpHandler(
vkuzkokovcbabd582014-11-06 13:53:54163 BrowserContext* browser_context) {
164 std::string frontend_url;
165#if defined(OS_ANDROID)
166 frontend_url = base::StringPrintf(kFrontEndURL, GetWebKitRevision().c_str());
167#endif
pfeldman10628762016-09-08 07:59:26168 DevToolsAgentHost::StartRemoteDebuggingServer(
dgozman102fee92015-04-20 15:45:46169 CreateSocketFactory(),
170 frontend_url,
yzshen6051dfd32015-10-20 19:23:25171 browser_context->GetPath(),
dgozman102fee92015-04-20 15:45:46172 base::FilePath(),
173 std::string(),
174 GetShellUserAgent());
vkuzkokovcbabd582014-11-06 13:53:54175}
176
pfeldman10628762016-09-08 07:59:26177// static
178void ShellDevToolsManagerDelegate::StopHttpHandler() {
179 DevToolsAgentHost::StopRemoteDebuggingServer();
180}
181
Pavel Feldman43f56b7c2016-08-30 00:04:35182ShellDevToolsManagerDelegate::ShellDevToolsManagerDelegate(
183 BrowserContext* browser_context)
184 : browser_context_(browser_context) {
dgozman252e18d2014-09-22 12:40:06185}
186
187ShellDevToolsManagerDelegate::~ShellDevToolsManagerDelegate() {
188}
189
Pavel Feldman43f56b7c2016-08-30 00:04:35190scoped_refptr<DevToolsAgentHost>
191ShellDevToolsManagerDelegate::CreateNewTarget(const GURL& url) {
192 Shell* shell = Shell::CreateNewWindow(browser_context_,
193 url,
194 nullptr,
195 gfx::Size());
196 return DevToolsAgentHost::GetOrCreateFor(shell->web_contents());
197}
198
pfeldman10628762016-09-08 07:59:26199std::string ShellDevToolsManagerDelegate::GetDiscoveryPageHTML() {
200#if defined(OS_ANDROID)
201 return std::string();
202#else
203 return ResourceBundle::GetSharedInstance().GetRawDataResource(
204 IDR_CONTENT_SHELL_DEVTOOLS_DISCOVERY_PAGE).as_string();
205#endif
206}
207
208std::string ShellDevToolsManagerDelegate::GetFrontendResource(
209 const std::string& path) {
chenwilliame88d8362017-03-21 02:34:30210#if defined(OS_ANDROID)
211 return std::string();
212#else
pfeldman10628762016-09-08 07:59:26213 return content::DevToolsFrontendHost::GetFrontendResource(path).as_string();
chenwilliame88d8362017-03-21 02:34:30214#endif
pfeldman10628762016-09-08 07:59:26215}
216
[email protected]ee75b8992012-01-27 07:53:57217} // namespace content