Home | History | Annotate | Download | only in devtools
      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 
     27 namespace chromecast {
     28 namespace shell {
     29 
     30 namespace {
     31 
     32 const int kDefaultRemoteDebuggingPort = 9222;
     33 
     34 #if defined(OS_ANDROID)
     35 class 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
     53 class 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 
     71 scoped_ptr<content::DevToolsHttpHandler::ServerSocketFactory>
     72 CreateSocketFactory(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 
     90 RemoteDebuggingServer::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 
    106 RemoteDebuggingServer::~RemoteDebuggingServer() {
    107   pref_port_.SetValue(0);
    108   OnPortChanged();
    109 }
    110 
    111 void 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