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. 4 5#include "chromecast/shell/browser/devtools/remote_debugging_server.h" 6 7#include "base/bind.h" 8#include "base/bind_helpers.h" 9#include "base/command_line.h" 10#include "base/files/file_path.h" 11#include "base/strings/stringprintf.h" 12#include "chromecast/common/chromecast_config.h" 13#include "chromecast/common/pref_names.h" 14#include "chromecast/shell/browser/devtools/cast_dev_tools_delegate.h" 15#include "content/public/browser/browser_context.h" 16#include "content/public/browser/browser_thread.h" 17#include "content/public/browser/devtools_http_handler.h" 18#include "content/public/common/content_switches.h" 19#include "content/public/common/user_agent.h" 20#include "net/socket/tcp_server_socket.h" 21 22#if defined(OS_ANDROID) 23#include "content/public/browser/android/devtools_auth.h" 24#include "net/socket/unix_domain_server_socket_posix.h" 25#endif // defined(OS_ANDROID) 26 27namespace chromecast { 28namespace shell { 29 30namespace { 31 32const int kDefaultRemoteDebuggingPort = 9222; 33 34#if defined(OS_ANDROID) 35class UnixDomainServerSocketFactory 36 : public content::DevToolsHttpHandler::ServerSocketFactory { 37 public: 38 explicit UnixDomainServerSocketFactory(const std::string& socket_name) 39 : content::DevToolsHttpHandler::ServerSocketFactory(socket_name, 0, 1) {} 40 41 private: 42 // content::DevToolsHttpHandler::ServerSocketFactory. 43 virtual scoped_ptr<net::ServerSocket> Create() const OVERRIDE { 44 return scoped_ptr<net::ServerSocket>( 45 new net::UnixDomainServerSocket( 46 base::Bind(&content::CanUserConnectToDevTools), 47 true /* use_abstract_namespace */)); 48 } 49 50 DISALLOW_COPY_AND_ASSIGN(UnixDomainServerSocketFactory); 51}; 52#else 53class TCPServerSocketFactory 54 : public content::DevToolsHttpHandler::ServerSocketFactory { 55 public: 56 TCPServerSocketFactory(const std::string& address, int port, int backlog) 57 : content::DevToolsHttpHandler::ServerSocketFactory( 58 address, port, backlog) {} 59 60 private: 61 // content::DevToolsHttpHandler::ServerSocketFactory. 62 virtual scoped_ptr<net::ServerSocket> Create() const OVERRIDE { 63 return scoped_ptr<net::ServerSocket>( 64 new net::TCPServerSocket(NULL, net::NetLog::Source())); 65 } 66 67 DISALLOW_COPY_AND_ASSIGN(TCPServerSocketFactory); 68}; 69#endif 70 71scoped_ptr<content::DevToolsHttpHandler::ServerSocketFactory> 72CreateSocketFactory(int port) { 73#if defined(OS_ANDROID) 74 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); 75 std::string socket_name = "content_shell_devtools_remote"; 76 if (command_line->HasSwitch(switches::kRemoteDebuggingSocketName)) { 77 socket_name = command_line->GetSwitchValueASCII( 78 switches::kRemoteDebuggingSocketName); 79 } 80 return scoped_ptr<content::DevToolsHttpHandler::ServerSocketFactory>( 81 new UnixDomainServerSocketFactory(socket_name)); 82#else 83 return scoped_ptr<content::DevToolsHttpHandler::ServerSocketFactory>( 84 new TCPServerSocketFactory("0.0.0.0", port, 1)); 85#endif 86} 87 88} // namespace 89 90RemoteDebuggingServer::RemoteDebuggingServer() 91 : devtools_http_handler_(NULL), 92 port_(0) { 93 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 94 pref_port_.Init(prefs::kRemoteDebuggingPort, 95 ChromecastConfig::GetInstance()->pref_service(), 96 base::Bind(&RemoteDebuggingServer::OnPortChanged, 97 base::Unretained(this))); 98 99 // Starts new dev tools, clearing port number saved in config. 100 // Remote debugging in production must be triggered only by config server. 101 pref_port_.SetValue(ShouldStartImmediately() ? 102 kDefaultRemoteDebuggingPort : 0); 103 OnPortChanged(); 104} 105 106RemoteDebuggingServer::~RemoteDebuggingServer() { 107 pref_port_.SetValue(0); 108 OnPortChanged(); 109} 110 111void RemoteDebuggingServer::OnPortChanged() { 112 int new_port = *pref_port_; 113 if (new_port < 0) { 114 new_port = 0; 115 } 116 VLOG(1) << "OnPortChanged called: old_port=" << port_ 117 << ", new_port=" << new_port; 118 119 if (new_port == port_) { 120 VLOG(1) << "Port has not been changed. Ignore silently."; 121 return; 122 } 123 124 if (devtools_http_handler_) { 125 LOG(INFO) << "Stop old devtools: port=" << port_; 126 // Note: Stop destroys devtools_http_handler_. 127 devtools_http_handler_->Stop(); 128 devtools_http_handler_ = NULL; 129 } 130 131 port_ = new_port; 132 if (port_ > 0) { 133 devtools_http_handler_ = content::DevToolsHttpHandler::Start( 134 CreateSocketFactory(port_), 135 std::string(), 136 new CastDevToolsDelegate(), 137 base::FilePath()); 138 LOG(INFO) << "Devtools started: port=" << port_; 139 } 140} 141 142} // namespace shell 143} // namespace chromecast 144