blob: 5219f35d5dc189e5c58c487f29ba3725a7722b74 [file] [log] [blame]
Avi Drissman4e1b7bc32022-09-15 14:03:501// Copyright 2013 The Chromium Authors
[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]90e6c5412013-04-16 22:45:2512#include "base/command_line.h"
[email protected]0e60fce2014-06-04 22:27:2013#include "base/files/file_path.h"
Avi Drissmanadac21992023-01-11 23:46:3914#include "base/functional/bind.h"
15#include "base/functional/callback.h"
[email protected]90e6c5412013-04-16 22:45:2516#include "base/strings/string_number_conversions.h"
[email protected]852b34ba2013-10-03 16:29:0617#include "base/strings/utf_string_conversions.h"
avi66a07722015-12-25 23:38:1218#include "build/build_config.h"
yzshen6051dfd32015-10-20 19:23:2519#include "content/public/browser/browser_context.h"
[email protected]852b34ba2013-10-03 16:29:0620#include "content/public/browser/devtools_agent_host.h"
Johannes Henkel9d14e4b82020-01-28 01:29:4121#include "content/public/browser/devtools_agent_host_client_channel.h"
pfeldmanf1a16942016-09-02 21:28:0022#include "content/public/browser/devtools_socket_factory.h"
[email protected]852b34ba2013-10-03 16:29:0623#include "content/public/browser/favicon_status.h"
24#include "content/public/browser/navigation_entry.h"
25#include "content/public/browser/render_view_host.h"
[email protected]eb040992012-10-10 16:56:0026#include "content/public/browser/web_contents.h"
[email protected]90e6c5412013-04-16 22:45:2527#include "content/public/common/content_switches.h"
[email protected]eb040992012-10-10 16:56:0028#include "content/public/common/url_constants.h"
[email protected]efd2c3f2014-03-11 09:57:2529#include "content/public/common/user_agent.h"
[email protected]de7d61ff2013-08-20 11:30:4130#include "content/shell/browser/shell.h"
dgozman102fee92015-04-20 15:45:4631#include "content/shell/common/shell_content_client.h"
dgozman4547460932017-06-22 03:04:3632#include "content/shell/common/shell_switches.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
Xiaohan Wangbd084422022-01-15 18:47:5139#if !BUILDFLAG(IS_ANDROID)
chenwilliame88d8362017-03-21 02:34:3040#include "content/public/browser/devtools_frontend_host.h"
41#endif
42
Xiaohan Wangbd084422022-01-15 18:47:5143#if BUILDFLAG(IS_ANDROID)
[email protected]ed6635e2012-10-27 00:44:0944#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
vkuzkokov79426762015-01-13 08:03:0052const int kBackLog = 10;
53
pfeldmanf7c18d0242016-09-08 19:54:2654base::subtle::Atomic32 g_last_used_port;
55
Xiaohan Wangbd084422022-01-15 18:47:5156#if BUILDFLAG(IS_ANDROID)
pfeldmanf1a16942016-09-02 21:28:0057class UnixDomainServerSocketFactory : public content::DevToolsSocketFactory {
byungchul38c3ae72014-08-25 23:27:4658 public:
59 explicit UnixDomainServerSocketFactory(const std::string& socket_name)
vkuzkokov79426762015-01-13 08:03:0060 : socket_name_(socket_name) {}
byungchul38c3ae72014-08-25 23:27:4661
Peter Boström9b036532021-10-28 23:37:2862 UnixDomainServerSocketFactory(const UnixDomainServerSocketFactory&) = delete;
63 UnixDomainServerSocketFactory& operator=(
64 const UnixDomainServerSocketFactory&) = delete;
65
byungchul38c3ae72014-08-25 23:27:4666 private:
pfeldmanf1a16942016-09-02 21:28:0067 // content::DevToolsSocketFactory.
dcheng6003e0b2016-04-09 18:42:3468 std::unique_ptr<net::ServerSocket> CreateForHttpServer() override {
69 std::unique_ptr<net::UnixDomainServerSocket> socket(
danakjc988f0be2019-05-17 20:48:0170 new net::UnixDomainServerSocket(
71 base::BindRepeating(&CanUserConnectToDevTools),
72 true /* use_abstract_namespace */));
tfarinaa7b245d2016-02-02 02:03:4973 if (socket->BindAndListen(socket_name_, kBackLog) != net::OK)
Lei Zhangdf291f62021-04-14 17:23:4474 return nullptr;
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_;
byungchul38c3ae72014-08-25 23:27:4685};
86#else
pfeldmanf1a16942016-09-02 21:28:0087class TCPServerSocketFactory : public content::DevToolsSocketFactory {
byungchul38c3ae72014-08-25 23:27:4688 public:
avi66a07722015-12-25 23:38:1289 TCPServerSocketFactory(const std::string& address, uint16_t port)
90 : address_(address), port_(port) {}
byungchul38c3ae72014-08-25 23:27:4691
Peter Boström9b036532021-10-28 23:37:2892 TCPServerSocketFactory(const TCPServerSocketFactory&) = delete;
93 TCPServerSocketFactory& operator=(const TCPServerSocketFactory&) = delete;
94
byungchul38c3ae72014-08-25 23:27:4695 private:
pfeldmanf1a16942016-09-02 21:28:0096 // content::DevToolsSocketFactory.
dcheng6003e0b2016-04-09 18:42:3497 std::unique_ptr<net::ServerSocket> CreateForHttpServer() override {
98 std::unique_ptr<net::ServerSocket> socket(
mikecironef22f9812016-10-04 03:40:1999 new net::TCPServerSocket(nullptr, net::NetLogSource()));
vkuzkokov79426762015-01-13 08:03:00100 if (socket->ListenWithAddressAndPort(address_, port_, kBackLog) != net::OK)
Lei Zhangdf291f62021-04-14 17:23:44101 return nullptr;
vkuzkokov79426762015-01-13 08:03:00102
pfeldmanf7c18d0242016-09-08 19:54:26103 net::IPEndPoint endpoint;
104 if (socket->GetLocalAddress(&endpoint) == net::OK)
105 base::subtle::NoBarrier_Store(&g_last_used_port, endpoint.port());
106
vkuzkokov79426762015-01-13 08:03:00107 return socket;
byungchul38c3ae72014-08-25 23:27:46108 }
109
pfeldmanf1a16942016-09-02 21:28:00110 std::unique_ptr<net::ServerSocket> CreateForTethering(
111 std::string* out_name) override {
112 return nullptr;
113 }
114
vkuzkokov79426762015-01-13 08:03:00115 std::string address_;
avi66a07722015-12-25 23:38:12116 uint16_t port_;
byungchul38c3ae72014-08-25 23:27:46117};
118#endif
119
pfeldmanf1a16942016-09-02 21:28:00120std::unique_ptr<content::DevToolsSocketFactory> CreateSocketFactory() {
avi83883c82014-12-23 00:08:49121 const base::CommandLine& command_line =
122 *base::CommandLine::ForCurrentProcess();
Xiaohan Wangbd084422022-01-15 18:47:51123#if BUILDFLAG(IS_ANDROID)
[email protected]90e6c5412013-04-16 22:45:25124 std::string socket_name = "content_shell_devtools_remote";
125 if (command_line.HasSwitch(switches::kRemoteDebuggingSocketName)) {
126 socket_name = command_line.GetSwitchValueASCII(
127 switches::kRemoteDebuggingSocketName);
128 }
pfeldmanf1a16942016-09-02 21:28:00129 return std::unique_ptr<content::DevToolsSocketFactory>(
byungchul38c3ae72014-08-25 23:27:46130 new UnixDomainServerSocketFactory(socket_name));
[email protected]90e6c5412013-04-16 22:45:25131#else
132 // See if the user specified a port on the command line (useful for
133 // automation). If not, use an ephemeral port by specifying 0.
avi66a07722015-12-25 23:38:12134 uint16_t port = 0;
[email protected]90e6c5412013-04-16 22:45:25135 if (command_line.HasSwitch(switches::kRemoteDebuggingPort)) {
136 int temp_port;
137 std::string port_str =
138 command_line.GetSwitchValueASCII(switches::kRemoteDebuggingPort);
139 if (base::StringToInt(port_str, &temp_port) &&
yzshen6051dfd32015-10-20 19:23:25140 temp_port >= 0 && temp_port < 65535) {
avi66a07722015-12-25 23:38:12141 port = static_cast<uint16_t>(temp_port);
[email protected]90e6c5412013-04-16 22:45:25142 } else {
143 DLOG(WARNING) << "Invalid http debugger port number " << temp_port;
144 }
145 }
Tiago Vignattia293c2c2023-03-28 20:31:04146 // By default listen to incoming DevTools connections on localhost.
147 std::string address_str = net::IPAddress::IPv4Localhost().ToString();
148 if (command_line.HasSwitch(switches::kRemoteDebuggingAddress)) {
149 net::IPAddress address;
150 address_str =
151 command_line.GetSwitchValueASCII(switches::kRemoteDebuggingAddress);
152 if (!address.AssignFromIPLiteral(address_str)) {
153 DLOG(WARNING) << "Invalid devtools server address: " << address_str;
154 }
155 }
pfeldmanf1a16942016-09-02 21:28:00156 return std::unique_ptr<content::DevToolsSocketFactory>(
Tiago Vignattia293c2c2023-03-28 20:31:04157 new TCPServerSocketFactory(address_str, port));
[email protected]ed6635e2012-10-27 00:44:09158#endif
[email protected]90e6c5412013-04-16 22:45:25159}
[email protected]852b34ba2013-10-03 16:29:06160
pfeldman10628762016-09-08 07:59:26161} // namespace
vkuzkokovcbabd582014-11-06 13:53:54162
dgozman252e18d2014-09-22 12:40:06163// ShellDevToolsManagerDelegate ----------------------------------------------
164
vkuzkokovcbabd582014-11-06 13:53:54165// static
pfeldmanf7c18d0242016-09-08 19:54:26166int ShellDevToolsManagerDelegate::GetHttpHandlerPort() {
167 return base::subtle::NoBarrier_Load(&g_last_used_port);
168}
169
170// static
pfeldman10628762016-09-08 07:59:26171void ShellDevToolsManagerDelegate::StartHttpHandler(
vkuzkokovcbabd582014-11-06 13:53:54172 BrowserContext* browser_context) {
173 std::string frontend_url;
pfeldman10628762016-09-08 07:59:26174 DevToolsAgentHost::StartRemoteDebuggingServer(
Pavel Feldmanc8a484b52018-02-07 21:07:32175 CreateSocketFactory(), browser_context->GetPath(), base::FilePath());
Pavel Feldman2b11e2352017-10-25 05:24:01176
177 const base::CommandLine& command_line =
178 *base::CommandLine::ForCurrentProcess();
179 if (command_line.HasSwitch(switches::kRemoteDebuggingPipe))
Dmitry Gozman8bbf58d2020-11-13 22:48:26180 DevToolsAgentHost::StartRemoteDebuggingPipeHandler(base::OnceClosure());
vkuzkokovcbabd582014-11-06 13:53:54181}
182
pfeldman10628762016-09-08 07:59:26183// static
184void ShellDevToolsManagerDelegate::StopHttpHandler() {
185 DevToolsAgentHost::StopRemoteDebuggingServer();
186}
187
Pavel Feldman43f56b7c2016-08-30 00:04:35188ShellDevToolsManagerDelegate::ShellDevToolsManagerDelegate(
189 BrowserContext* browser_context)
190 : browser_context_(browser_context) {
dgozman252e18d2014-09-22 12:40:06191}
192
193ShellDevToolsManagerDelegate::~ShellDevToolsManagerDelegate() {
194}
195
Andrey Lushnikov36299bc2018-08-23 22:09:54196BrowserContext* ShellDevToolsManagerDelegate::GetDefaultBrowserContext() {
197 return browser_context_;
198}
199
Andrey Lushnikovdf1651982018-09-14 19:00:37200void ShellDevToolsManagerDelegate::ClientAttached(
Johannes Henkel9d14e4b82020-01-28 01:29:41201 content::DevToolsAgentHostClientChannel* channel) {
Andrey Lushnikovdf1651982018-09-14 19:00:37202 // Make sure we don't receive notifications twice for the same client.
Johannes Henkel9d14e4b82020-01-28 01:29:41203 CHECK(clients_.find(channel->GetClient()) == clients_.end());
204 clients_.insert(channel->GetClient());
Andrey Lushnikovdf1651982018-09-14 19:00:37205}
206
207void ShellDevToolsManagerDelegate::ClientDetached(
Johannes Henkel9d14e4b82020-01-28 01:29:41208 content::DevToolsAgentHostClientChannel* channel) {
209 clients_.erase(channel->GetClient());
Andrey Lushnikovdf1651982018-09-14 19:00:37210}
211
Danil Somsikovd5b36842022-12-16 11:24:50212scoped_refptr<DevToolsAgentHost> ShellDevToolsManagerDelegate::CreateNewTarget(
213 const GURL& url,
214 bool for_tab) {
danakj24577b12020-05-13 22:38:18215 Shell* shell = Shell::CreateNewWindow(browser_context_, url, nullptr,
216 Shell::GetShellDefaultSize());
Danil Somsikovd5b36842022-12-16 11:24:50217 return for_tab ? DevToolsAgentHost::GetOrCreateForTab(shell->web_contents())
218 : DevToolsAgentHost::GetOrCreateFor(shell->web_contents());
Pavel Feldman43f56b7c2016-08-30 00:04:35219}
220
pfeldman10628762016-09-08 07:59:26221std::string ShellDevToolsManagerDelegate::GetDiscoveryPageHTML() {
Xiaohan Wangbd084422022-01-15 18:47:51222#if BUILDFLAG(IS_ANDROID)
pfeldman10628762016-09-08 07:59:26223 return std::string();
224#else
Kristian Kirsb9e270512020-07-08 15:21:20225 return ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(
226 IDR_CONTENT_SHELL_DEVTOOLS_DISCOVERY_PAGE);
pfeldman10628762016-09-08 07:59:26227#endif
228}
229
Pavel Feldmanc8a484b52018-02-07 21:07:32230bool ShellDevToolsManagerDelegate::HasBundledFrontendResources() {
Xiaohan Wangbd084422022-01-15 18:47:51231#if BUILDFLAG(IS_ANDROID)
Pavel Feldmanc8a484b52018-02-07 21:07:32232 return false;
Nico Weber2771b0f2021-08-16 17:16:24233#else
Pavel Feldmanc8a484b52018-02-07 21:07:32234 return true;
Nico Weber2771b0f2021-08-16 17:16:24235#endif
pfeldman10628762016-09-08 07:59:26236}
237
[email protected]ee75b8992012-01-27 07:53:57238} // namespace content