blob: cc09d201130075849691da3f6ce257d0343aabe4 [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"
[email protected]90e6c5412013-04-16 22:45:2516#include "base/strings/string_number_conversions.h"
[email protected]8dffd2c2013-12-02 14:14:3817#include "base/strings/stringprintf.h"
[email protected]852b34ba2013-10-03 16:29:0618#include "base/strings/utf_string_conversions.h"
avi66a07722015-12-25 23:38:1219#include "build/build_config.h"
yzshen6051dfd32015-10-20 19:23:2520#include "content/public/browser/browser_context.h"
[email protected]852b34ba2013-10-03 16:29:0621#include "content/public/browser/devtools_agent_host.h"
Johannes Henkel9d14e4b82020-01-28 01:29:4122#include "content/public/browser/devtools_agent_host_client_channel.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"
Kent Tamuraf92649d882018-12-03 09:07:4732#include "content/shell/browser/web_test/secondary_test_window_observer.h"
dgozman102fee92015-04-20 15:45:4633#include "content/shell/common/shell_content_client.h"
dgozman4547460932017-06-22 03:04:3634#include "content/shell/common/shell_switches.h"
thakisda47dac2017-02-27 14:35:3035#include "content/shell/grit/shell_resources.h"
vkuzkokov79426762015-01-13 08:03:0036#include "net/base/net_errors.h"
mikecironef22f9812016-10-04 03:40:1937#include "net/log/net_log_source.h"
byungchul38c3ae72014-08-25 23:27:4638#include "net/socket/tcp_server_socket.h"
[email protected]ee75b8992012-01-27 07:53:5739#include "ui/base/resource/resource_bundle.h"
40
chenwilliame88d8362017-03-21 02:34:3041#if !defined(OS_ANDROID)
42#include "content/public/browser/devtools_frontend_host.h"
43#endif
44
[email protected]ed6635e2012-10-27 00:44:0945#if defined(OS_ANDROID)
46#include "content/public/browser/android/devtools_auth.h"
byungchul38c3ae72014-08-25 23:27:4647#include "net/socket/unix_domain_server_socket_posix.h"
[email protected]90e6c5412013-04-16 22:45:2548#endif
[email protected]ed6635e2012-10-27 00:44:0949
vkuzkokovcbabd582014-11-06 13:53:5450namespace content {
[email protected]852b34ba2013-10-03 16:29:0651
[email protected]ed6635e2012-10-27 00:44:0952namespace {
[email protected]90e6c5412013-04-16 22:45:2553
vkuzkokov79426762015-01-13 08:03:0054const int kBackLog = 10;
55
pfeldmanf7c18d0242016-09-08 19:54:2656base::subtle::Atomic32 g_last_used_port;
57
byungchul38c3ae72014-08-25 23:27:4658#if defined(OS_ANDROID)
pfeldmanf1a16942016-09-02 21:28:0059class UnixDomainServerSocketFactory : public content::DevToolsSocketFactory {
byungchul38c3ae72014-08-25 23:27:4660 public:
61 explicit UnixDomainServerSocketFactory(const std::string& socket_name)
vkuzkokov79426762015-01-13 08:03:0062 : socket_name_(socket_name) {}
byungchul38c3ae72014-08-25 23:27:4663
64 private:
pfeldmanf1a16942016-09-02 21:28:0065 // content::DevToolsSocketFactory.
dcheng6003e0b2016-04-09 18:42:3466 std::unique_ptr<net::ServerSocket> CreateForHttpServer() override {
67 std::unique_ptr<net::UnixDomainServerSocket> socket(
danakjc988f0be2019-05-17 20:48:0168 new net::UnixDomainServerSocket(
69 base::BindRepeating(&CanUserConnectToDevTools),
70 true /* use_abstract_namespace */));
tfarinaa7b245d2016-02-02 02:03:4971 if (socket->BindAndListen(socket_name_, kBackLog) != net::OK)
dcheng6003e0b2016-04-09 18:42:3472 return std::unique_ptr<net::ServerSocket>();
vkuzkokov79426762015-01-13 08:03:0073
tfarinaa7b245d2016-02-02 02:03:4974 return std::move(socket);
byungchul38c3ae72014-08-25 23:27:4675 }
76
pfeldmanf1a16942016-09-02 21:28:0077 std::unique_ptr<net::ServerSocket> CreateForTethering(
78 std::string* out_name) override {
79 return nullptr;
80 }
81
vkuzkokov79426762015-01-13 08:03:0082 std::string socket_name_;
83
byungchul38c3ae72014-08-25 23:27:4684 DISALLOW_COPY_AND_ASSIGN(UnixDomainServerSocketFactory);
85};
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
92 private:
pfeldmanf1a16942016-09-02 21:28:0093 // content::DevToolsSocketFactory.
dcheng6003e0b2016-04-09 18:42:3494 std::unique_ptr<net::ServerSocket> CreateForHttpServer() override {
95 std::unique_ptr<net::ServerSocket> socket(
mikecironef22f9812016-10-04 03:40:1996 new net::TCPServerSocket(nullptr, net::NetLogSource()));
vkuzkokov79426762015-01-13 08:03:0097 if (socket->ListenWithAddressAndPort(address_, port_, kBackLog) != net::OK)
dcheng6003e0b2016-04-09 18:42:3498 return std::unique_ptr<net::ServerSocket>();
vkuzkokov79426762015-01-13 08:03:0099
pfeldmanf7c18d0242016-09-08 19:54:26100 net::IPEndPoint endpoint;
101 if (socket->GetLocalAddress(&endpoint) == net::OK)
102 base::subtle::NoBarrier_Store(&g_last_used_port, endpoint.port());
103
vkuzkokov79426762015-01-13 08:03:00104 return socket;
byungchul38c3ae72014-08-25 23:27:46105 }
106
pfeldmanf1a16942016-09-02 21:28:00107 std::unique_ptr<net::ServerSocket> CreateForTethering(
108 std::string* out_name) override {
109 return nullptr;
110 }
111
vkuzkokov79426762015-01-13 08:03:00112 std::string address_;
avi66a07722015-12-25 23:38:12113 uint16_t port_;
vkuzkokov79426762015-01-13 08:03:00114
byungchul38c3ae72014-08-25 23:27:46115 DISALLOW_COPY_AND_ASSIGN(TCPServerSocketFactory);
116};
117#endif
118
pfeldmanf1a16942016-09-02 21:28:00119std::unique_ptr<content::DevToolsSocketFactory> CreateSocketFactory() {
avi83883c82014-12-23 00:08:49120 const base::CommandLine& command_line =
121 *base::CommandLine::ForCurrentProcess();
[email protected]90e6c5412013-04-16 22:45:25122#if defined(OS_ANDROID)
123 std::string socket_name = "content_shell_devtools_remote";
124 if (command_line.HasSwitch(switches::kRemoteDebuggingSocketName)) {
125 socket_name = command_line.GetSwitchValueASCII(
126 switches::kRemoteDebuggingSocketName);
127 }
pfeldmanf1a16942016-09-02 21:28:00128 return std::unique_ptr<content::DevToolsSocketFactory>(
byungchul38c3ae72014-08-25 23:27:46129 new UnixDomainServerSocketFactory(socket_name));
[email protected]90e6c5412013-04-16 22:45:25130#else
131 // See if the user specified a port on the command line (useful for
132 // automation). If not, use an ephemeral port by specifying 0.
avi66a07722015-12-25 23:38:12133 uint16_t port = 0;
[email protected]90e6c5412013-04-16 22:45:25134 if (command_line.HasSwitch(switches::kRemoteDebuggingPort)) {
135 int temp_port;
136 std::string port_str =
137 command_line.GetSwitchValueASCII(switches::kRemoteDebuggingPort);
138 if (base::StringToInt(port_str, &temp_port) &&
yzshen6051dfd32015-10-20 19:23:25139 temp_port >= 0 && temp_port < 65535) {
avi66a07722015-12-25 23:38:12140 port = static_cast<uint16_t>(temp_port);
[email protected]90e6c5412013-04-16 22:45:25141 } else {
142 DLOG(WARNING) << "Invalid http debugger port number " << temp_port;
143 }
144 }
pfeldmanf1a16942016-09-02 21:28:00145 return std::unique_ptr<content::DevToolsSocketFactory>(
vkuzkokov79426762015-01-13 08:03:00146 new TCPServerSocketFactory("127.0.0.1", port));
[email protected]ed6635e2012-10-27 00:44:09147#endif
[email protected]90e6c5412013-04-16 22:45:25148}
[email protected]852b34ba2013-10-03 16:29:06149
pfeldman10628762016-09-08 07:59:26150} // namespace
vkuzkokovcbabd582014-11-06 13:53:54151
dgozman252e18d2014-09-22 12:40:06152// ShellDevToolsManagerDelegate ----------------------------------------------
153
vkuzkokovcbabd582014-11-06 13:53:54154// static
pfeldmanf7c18d0242016-09-08 19:54:26155int ShellDevToolsManagerDelegate::GetHttpHandlerPort() {
156 return base::subtle::NoBarrier_Load(&g_last_used_port);
157}
158
159// static
pfeldman10628762016-09-08 07:59:26160void ShellDevToolsManagerDelegate::StartHttpHandler(
vkuzkokovcbabd582014-11-06 13:53:54161 BrowserContext* browser_context) {
162 std::string frontend_url;
pfeldman10628762016-09-08 07:59:26163 DevToolsAgentHost::StartRemoteDebuggingServer(
Pavel Feldmanc8a484b52018-02-07 21:07:32164 CreateSocketFactory(), browser_context->GetPath(), base::FilePath());
Pavel Feldman2b11e2352017-10-25 05:24:01165
166 const base::CommandLine& command_line =
167 *base::CommandLine::ForCurrentProcess();
168 if (command_line.HasSwitch(switches::kRemoteDebuggingPipe))
169 DevToolsAgentHost::StartRemoteDebuggingPipeHandler();
vkuzkokovcbabd582014-11-06 13:53:54170}
171
pfeldman10628762016-09-08 07:59:26172// static
173void ShellDevToolsManagerDelegate::StopHttpHandler() {
174 DevToolsAgentHost::StopRemoteDebuggingServer();
175}
176
Pavel Feldman43f56b7c2016-08-30 00:04:35177ShellDevToolsManagerDelegate::ShellDevToolsManagerDelegate(
178 BrowserContext* browser_context)
179 : browser_context_(browser_context) {
dgozman252e18d2014-09-22 12:40:06180}
181
182ShellDevToolsManagerDelegate::~ShellDevToolsManagerDelegate() {
183}
184
Andrey Lushnikov36299bc2018-08-23 22:09:54185BrowserContext* ShellDevToolsManagerDelegate::GetDefaultBrowserContext() {
186 return browser_context_;
187}
188
Andrey Lushnikovdf1651982018-09-14 19:00:37189void ShellDevToolsManagerDelegate::ClientAttached(
Johannes Henkel9d14e4b82020-01-28 01:29:41190 content::DevToolsAgentHostClientChannel* channel) {
Andrey Lushnikovdf1651982018-09-14 19:00:37191 // Make sure we don't receive notifications twice for the same client.
Johannes Henkel9d14e4b82020-01-28 01:29:41192 CHECK(clients_.find(channel->GetClient()) == clients_.end());
193 clients_.insert(channel->GetClient());
Andrey Lushnikovdf1651982018-09-14 19:00:37194}
195
196void ShellDevToolsManagerDelegate::ClientDetached(
Johannes Henkel9d14e4b82020-01-28 01:29:41197 content::DevToolsAgentHostClientChannel* channel) {
198 clients_.erase(channel->GetClient());
Andrey Lushnikovdf1651982018-09-14 19:00:37199}
200
Pavel Feldman43f56b7c2016-08-30 00:04:35201scoped_refptr<DevToolsAgentHost>
202ShellDevToolsManagerDelegate::CreateNewTarget(const GURL& url) {
203 Shell* shell = Shell::CreateNewWindow(browser_context_,
204 url,
205 nullptr,
206 gfx::Size());
Kent Tamuracd3ebc42018-05-16 06:44:22207 if (switches::IsRunWebTestsSwitchPresent())
dgozman4547460932017-06-22 03:04:36208 SecondaryTestWindowObserver::CreateForWebContents(shell->web_contents());
Pavel Feldman43f56b7c2016-08-30 00:04:35209 return DevToolsAgentHost::GetOrCreateFor(shell->web_contents());
210}
211
pfeldman10628762016-09-08 07:59:26212std::string ShellDevToolsManagerDelegate::GetDiscoveryPageHTML() {
213#if defined(OS_ANDROID)
214 return std::string();
215#else
Lei Zhangcf30efc2017-10-04 21:31:24216 return ui::ResourceBundle::GetSharedInstance()
217 .GetRawDataResource(IDR_CONTENT_SHELL_DEVTOOLS_DISCOVERY_PAGE)
218 .as_string();
pfeldman10628762016-09-08 07:59:26219#endif
220}
221
Pavel Feldmanc8a484b52018-02-07 21:07:32222bool ShellDevToolsManagerDelegate::HasBundledFrontendResources() {
chenwilliame88d8362017-03-21 02:34:30223#if defined(OS_ANDROID)
Pavel Feldmanc8a484b52018-02-07 21:07:32224 return false;
chenwilliame88d8362017-03-21 02:34:30225#endif
Pavel Feldmanc8a484b52018-02-07 21:07:32226 return true;
pfeldman10628762016-09-08 07:59:26227}
228
[email protected]ee75b8992012-01-27 07:53:57229} // namespace content