1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chromecast/browser/devtools/remote_debugging_server.h"
8 #include "base/bind_helpers.h"
9 #include "base/command_line.h"
10 #include "base/files/file_path.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/stringprintf.h"
13 #include "chromecast/browser/cast_browser_process.h"
14 #include "chromecast/browser/devtools/cast_dev_tools_delegate.h"
15 #include "chromecast/common/cast_content_client.h"
16 #include "chromecast/common/pref_names.h"
17 #include "components/devtools_http_handler/devtools_http_handler.h"
18 #include "content/public/browser/browser_context.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/common/content_switches.h"
21 #include "content/public/common/user_agent.h"
22 #include "net/base/net_errors.h"
23 #include "net/socket/tcp_server_socket.h"
25 #if defined(OS_ANDROID)
26 #include "content/public/browser/android/devtools_auth.h"
27 #include "net/socket/unix_domain_server_socket_posix.h"
28 #endif // defined(OS_ANDROID)
30 using devtools_http_handler::DevToolsHttpHandler
;
32 namespace chromecast
{
37 const char kFrontEndURL
[] =
38 "https://chrome-devtools-frontend.appspot.com/serve_rev/%s/inspector.html";
39 const uint16 kDefaultRemoteDebuggingPort
= 9222;
41 const int kBackLog
= 10;
43 #if defined(OS_ANDROID)
44 class UnixDomainServerSocketFactory
45 : public DevToolsHttpHandler::ServerSocketFactory
{
47 explicit UnixDomainServerSocketFactory(const std::string
& socket_name
)
48 : socket_name_(socket_name
) {}
51 // devtools_http_handler::DevToolsHttpHandler::ServerSocketFactory.
52 scoped_ptr
<net::ServerSocket
> CreateForHttpServer() override
{
53 scoped_ptr
<net::ServerSocket
> socket(
54 new net::UnixDomainServerSocket(
55 base::Bind(&content::CanUserConnectToDevTools
),
56 true /* use_abstract_namespace */));
57 if (socket
->ListenWithAddressAndPort(socket_name_
, 0, kBackLog
) != net::OK
)
58 return scoped_ptr
<net::ServerSocket
>();
63 std::string socket_name_
;
65 DISALLOW_COPY_AND_ASSIGN(UnixDomainServerSocketFactory
);
68 class TCPServerSocketFactory
69 : public DevToolsHttpHandler::ServerSocketFactory
{
71 TCPServerSocketFactory(const std::string
& address
, uint16 port
)
72 : address_(address
), port_(port
) {
76 // devtools_http_handler::DevToolsHttpHandler::ServerSocketFactory.
77 scoped_ptr
<net::ServerSocket
> CreateForHttpServer() override
{
78 scoped_ptr
<net::ServerSocket
> socket(
79 new net::TCPServerSocket(nullptr, net::NetLog::Source()));
80 if (socket
->ListenWithAddressAndPort(address_
, port_
, kBackLog
) != net::OK
)
81 return scoped_ptr
<net::ServerSocket
>();
89 DISALLOW_COPY_AND_ASSIGN(TCPServerSocketFactory
);
93 scoped_ptr
<DevToolsHttpHandler::ServerSocketFactory
>
94 CreateSocketFactory(uint16 port
) {
95 #if defined(OS_ANDROID)
96 base::CommandLine
* command_line
= base::CommandLine::ForCurrentProcess();
97 std::string socket_name
= "cast_shell_devtools_remote";
98 if (command_line
->HasSwitch(switches::kRemoteDebuggingSocketName
)) {
99 socket_name
= command_line
->GetSwitchValueASCII(
100 switches::kRemoteDebuggingSocketName
);
102 return scoped_ptr
<DevToolsHttpHandler::ServerSocketFactory
>(
103 new UnixDomainServerSocketFactory(socket_name
));
105 return scoped_ptr
<DevToolsHttpHandler::ServerSocketFactory
>(
106 new TCPServerSocketFactory("0.0.0.0", port
));
110 std::string
GetFrontendUrl() {
111 return base::StringPrintf(kFrontEndURL
, content::GetWebKitRevision().c_str());
116 RemoteDebuggingServer::RemoteDebuggingServer()
117 : port_(kDefaultRemoteDebuggingPort
) {
118 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
119 pref_enabled_
.Init(prefs::kEnableRemoteDebugging
,
120 CastBrowserProcess::GetInstance()->pref_service(),
121 base::Bind(&RemoteDebuggingServer::OnEnabledChanged
,
122 base::Unretained(this)));
124 std::string port_str
=
125 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
126 switches::kRemoteDebuggingPort
);
127 if (!port_str
.empty()) {
128 int port
= kDefaultRemoteDebuggingPort
;
129 if (base::StringToInt(port_str
, &port
)) {
130 port_
= static_cast<uint16
>(port
);
132 port_
= kDefaultRemoteDebuggingPort
;
136 // Starts new dev tools, clearing port number saved in config.
137 // Remote debugging in production must be triggered only by config server.
138 pref_enabled_
.SetValue(ShouldStartImmediately() && port_
!= 0);
142 RemoteDebuggingServer::~RemoteDebuggingServer() {
143 pref_enabled_
.SetValue(false);
147 void RemoteDebuggingServer::OnEnabledChanged() {
148 bool enabled
= *pref_enabled_
&& port_
!= 0;
149 if (enabled
&& !devtools_http_handler_
) {
150 devtools_http_handler_
.reset(new DevToolsHttpHandler(
151 CreateSocketFactory(port_
),
153 new CastDevToolsDelegate(),
158 LOG(INFO
) << "Devtools started: port=" << port_
;
159 } else if (!enabled
&& devtools_http_handler_
) {
160 LOG(INFO
) << "Stop devtools: port=" << port_
;
161 devtools_http_handler_
.reset();
166 } // namespace chromecast