Home | History | Annotate | Download | only in devtools
      1 // Copyright 2013 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 "chrome/browser/devtools/android_device.h"
      6 
      7 #include "base/strings/string_util.h"
      8 #include "base/strings/stringprintf.h"
      9 #include "base/threading/thread.h"
     10 #include "chrome/browser/devtools/adb/android_rsa.h"
     11 #include "chrome/browser/devtools/adb/android_usb_device.h"
     12 #include "chrome/browser/devtools/adb_client_socket.h"
     13 #include "net/base/net_errors.h"
     14 
     15 using content::BrowserThread;
     16 
     17 namespace {
     18 
     19 const char kHostTransportCommand[] = "host:transport:%s|%s";
     20 const char kHostDevicesCommand[] = "host:devices";
     21 const char kLocalAbstractCommand[] = "localabstract:%s";
     22 
     23 const int kAdbPort = 5037;
     24 const int kBufferSize = 16 * 1024;
     25 
     26 // AdbDeviceImpl --------------------------------------------------------------
     27 
     28 class AdbDeviceImpl : public AndroidDevice {
     29  public:
     30   AdbDeviceImpl(const std::string& serial, bool is_connected);
     31   virtual void RunCommand(const std::string& command,
     32                           const CommandCallback& callback) OVERRIDE;
     33   virtual void OpenSocket(const std::string& name,
     34                           const SocketCallback& callback) OVERRIDE;
     35  private:
     36   virtual ~AdbDeviceImpl() {}
     37 };
     38 
     39 AdbDeviceImpl::AdbDeviceImpl(const std::string& serial, bool is_connected)
     40     : AndroidDevice(serial, is_connected) {
     41 }
     42 
     43 void AdbDeviceImpl::RunCommand(const std::string& command,
     44                                const CommandCallback& callback) {
     45   std::string query = base::StringPrintf(kHostTransportCommand,
     46                                          serial().c_str(), command.c_str());
     47   AdbClientSocket::AdbQuery(kAdbPort, query, callback);
     48 }
     49 
     50 void AdbDeviceImpl::OpenSocket(const std::string& name,
     51                                const SocketCallback& callback) {
     52   std::string socket_name =
     53       base::StringPrintf(kLocalAbstractCommand, name.c_str());
     54   AdbClientSocket::TransportQuery(kAdbPort, serial(), socket_name, callback);
     55 }
     56 
     57 // UsbDeviceImpl --------------------------------------------------------------
     58 
     59 class UsbDeviceImpl : public AndroidDevice {
     60  public:
     61   explicit UsbDeviceImpl(AndroidUsbDevice* device);
     62   virtual void RunCommand(const std::string& command,
     63                           const CommandCallback& callback) OVERRIDE;
     64   virtual void OpenSocket(const std::string& name,
     65                           const SocketCallback& callback) OVERRIDE;
     66  private:
     67   void OnOpenSocket(const SocketCallback& callback,
     68                     net::StreamSocket* socket,
     69                     int result);
     70   void OpenedForCommand(const CommandCallback& callback,
     71                         net::StreamSocket* socket,
     72                         int result);
     73   void OnRead(net::StreamSocket* socket,
     74               scoped_refptr<net::IOBuffer> buffer,
     75               const std::string& data,
     76               const CommandCallback& callback,
     77               int result);
     78 
     79   virtual ~UsbDeviceImpl() {}
     80   scoped_refptr<AndroidUsbDevice> device_;
     81 };
     82 
     83 
     84 UsbDeviceImpl::UsbDeviceImpl(AndroidUsbDevice* device)
     85     : AndroidDevice(device->serial(), device->is_connected()),
     86       device_(device) {
     87   device_->InitOnCallerThread();
     88 }
     89 
     90 void UsbDeviceImpl::RunCommand(const std::string& command,
     91                                const CommandCallback& callback) {
     92   net::StreamSocket* socket = device_->CreateSocket(command);
     93   int result = socket->Connect(base::Bind(&UsbDeviceImpl::OpenedForCommand,
     94                                           this, callback, socket));
     95   if (result != net::ERR_IO_PENDING)
     96     callback.Run(result, std::string());
     97 }
     98 
     99 void UsbDeviceImpl::OpenSocket(const std::string& name,
    100                                const SocketCallback& callback) {
    101   std::string socket_name =
    102       base::StringPrintf(kLocalAbstractCommand, name.c_str());
    103   net::StreamSocket* socket = device_->CreateSocket(socket_name);
    104   int result = socket->Connect(base::Bind(&UsbDeviceImpl::OnOpenSocket, this,
    105                                           callback, socket));
    106   if (result != net::ERR_IO_PENDING)
    107     callback.Run(result, NULL);
    108 }
    109 
    110 void UsbDeviceImpl::OnOpenSocket(const SocketCallback& callback,
    111                   net::StreamSocket* socket,
    112                   int result) {
    113   callback.Run(result, result == net::OK ? socket : NULL);
    114 }
    115 
    116 void UsbDeviceImpl::OpenedForCommand(const CommandCallback& callback,
    117                                      net::StreamSocket* socket,
    118                                      int result) {
    119   if (result != net::OK) {
    120     callback.Run(result, std::string());
    121     return;
    122   }
    123   scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kBufferSize);
    124   result = socket->Read(buffer, kBufferSize,
    125                         base::Bind(&UsbDeviceImpl::OnRead, this,
    126                                    socket, buffer, std::string(), callback));
    127   if (result != net::ERR_IO_PENDING)
    128     OnRead(socket, buffer, std::string(), callback, result);
    129 }
    130 
    131 void UsbDeviceImpl::OnRead(net::StreamSocket* socket,
    132                            scoped_refptr<net::IOBuffer> buffer,
    133                            const std::string& data,
    134                            const CommandCallback& callback,
    135                            int result) {
    136   if (result <= 0) {
    137     callback.Run(result, result == 0 ? data : std::string());
    138     delete socket;
    139     return;
    140   }
    141 
    142   std::string new_data = data + std::string(buffer->data(), result);
    143   result = socket->Read(buffer, kBufferSize,
    144                         base::Bind(&UsbDeviceImpl::OnRead, this,
    145                                    socket, buffer, new_data, callback));
    146   if (result != net::ERR_IO_PENDING)
    147     OnRead(socket, buffer, new_data, callback, result);
    148 }
    149 
    150 // AdbDeviceProvider -------------------------------------------
    151 
    152 class AdbDeviceProvider: public AndroidDeviceProvider {
    153  public:
    154   virtual void QueryDevices(const QueryDevicesCallback& callback) OVERRIDE;
    155  private:
    156   void QueryDevicesOnAdbThread(const QueryDevicesCallback& callback);
    157   void ReceivedAdbDevices(const QueryDevicesCallback& callback, int result,
    158                           const std::string& response);
    159 
    160   virtual ~AdbDeviceProvider();
    161 };
    162 
    163 AdbDeviceProvider::~AdbDeviceProvider() {
    164 }
    165 
    166 void AdbDeviceProvider::QueryDevices(const QueryDevicesCallback& callback) {
    167   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    168 
    169   adb_thread_->message_loop()->PostTask(
    170         FROM_HERE, base::Bind(&AdbDeviceProvider::QueryDevicesOnAdbThread,
    171         this, callback));
    172 }
    173 
    174 void AdbDeviceProvider::QueryDevicesOnAdbThread(
    175     const QueryDevicesCallback& callback) {
    176   DCHECK_EQ(adb_thread_->message_loop(), base::MessageLoop::current());
    177 
    178   AdbClientSocket::AdbQuery(
    179       kAdbPort, kHostDevicesCommand,
    180       base::Bind(&AdbDeviceProvider::ReceivedAdbDevices, this, callback));
    181 }
    182 
    183 void AdbDeviceProvider::ReceivedAdbDevices(const QueryDevicesCallback& callback,
    184                                            int result_code,
    185                                            const std::string& response) {
    186   DCHECK_EQ(adb_thread_->message_loop(), base::MessageLoop::current());
    187 
    188   AndroidDevices result;
    189 
    190 #if defined(DEBUG_DEVTOOLS)
    191   // For desktop remote debugging.
    192   result.push_back(new AdbDeviceImpl("", true));
    193 #endif  // defined(DEBUG_DEVTOOLS)
    194 
    195   std::vector<std::string> serials;
    196   Tokenize(response, "\n", &serials);
    197   for (size_t i = 0; i < serials.size(); ++i) {
    198     std::vector<std::string> tokens;
    199     Tokenize(serials[i], "\t ", &tokens);
    200     bool offline = tokens.size() > 1 && tokens[1] == "offline";
    201     result.push_back(new AdbDeviceImpl(tokens[0], !offline));
    202   }
    203 
    204   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
    205                           base::Bind(&AdbDeviceProvider::RunCallbackOnUIThread,
    206                           callback, result));
    207 }
    208 
    209 // UsbDeviceProvider -------------------------------------------
    210 
    211 class UsbDeviceProvider: public AndroidDeviceProvider {
    212  public:
    213   explicit UsbDeviceProvider(Profile* profile);
    214 
    215   virtual void QueryDevices(const QueryDevicesCallback& callback) OVERRIDE;
    216  private:
    217   virtual ~UsbDeviceProvider();
    218   void WrapDevicesOnAdbThread(const QueryDevicesCallback& callback,
    219                               const AndroidUsbDevices& devices);
    220   void EnumeratedDevices(const QueryDevicesCallback& callback,
    221                          const AndroidUsbDevices& devices);
    222 
    223   scoped_ptr<crypto::RSAPrivateKey>  rsa_key_;
    224 };
    225 
    226 UsbDeviceProvider::UsbDeviceProvider(Profile* profile){
    227   rsa_key_.reset(AndroidRSAPrivateKey(profile));
    228 }
    229 
    230 UsbDeviceProvider::~UsbDeviceProvider() {
    231 }
    232 
    233 void UsbDeviceProvider::QueryDevices(const QueryDevicesCallback& callback) {
    234   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    235   AndroidUsbDevice::Enumerate(rsa_key_.get(),
    236                               base::Bind(&UsbDeviceProvider::EnumeratedDevices,
    237                               this, callback));
    238 }
    239 
    240 void UsbDeviceProvider::EnumeratedDevices(const QueryDevicesCallback& callback,
    241                                           const AndroidUsbDevices& devices) {
    242   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    243   adb_thread_->message_loop()->PostTask(FROM_HERE,
    244                           base::Bind(&UsbDeviceProvider::WrapDevicesOnAdbThread,
    245                           this, callback, devices));
    246 }
    247 
    248 void UsbDeviceProvider::WrapDevicesOnAdbThread(
    249     const QueryDevicesCallback& callback,const AndroidUsbDevices& devices) {
    250   DCHECK_EQ(adb_thread_->message_loop(), base::MessageLoop::current());
    251   AndroidDevices result;
    252   for (AndroidUsbDevices::const_iterator it = devices.begin();
    253       it != devices.end(); ++it)
    254     result.push_back(new UsbDeviceImpl(*it));
    255 
    256   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
    257                           base::Bind(&UsbDeviceProvider::RunCallbackOnUIThread,
    258                           callback, result));
    259 }
    260 
    261 } // namespace
    262 
    263 // AndroidDevice -------------------------------------------
    264 
    265 AndroidDevice::AndroidDevice(const std::string& serial, bool is_connected)
    266     : serial_(serial),
    267       is_connected_(is_connected) {
    268 }
    269 
    270 void AndroidDevice::HttpQuery(
    271     const std::string& la_name,
    272     const std::string& request,
    273     const CommandCallback& callback) {
    274   OpenSocket(la_name, base::Bind(&AndroidDevice::OnHttpSocketOpened, this,
    275                                  request, callback));
    276 }
    277 
    278 void AndroidDevice::HttpUpgrade(
    279     const std::string& la_name,
    280     const std::string& request,
    281     const SocketCallback& callback) {
    282   OpenSocket(la_name, base::Bind(&AndroidDevice::OnHttpSocketOpened2, this,
    283                                  request, callback));
    284 }
    285 
    286 AndroidDevice::~AndroidDevice() {
    287 }
    288 
    289 void AndroidDevice::OnHttpSocketOpened(
    290     const std::string& request,
    291     const CommandCallback& callback,
    292     int result,
    293     net::StreamSocket* socket) {
    294   if (result != net::OK) {
    295     callback.Run(result, std::string());
    296     return;
    297   }
    298   AdbClientSocket::HttpQuery(socket, request, callback);
    299 }
    300 
    301 void AndroidDevice::OnHttpSocketOpened2(
    302     const std::string& request,
    303     const SocketCallback& callback,
    304     int result,
    305     net::StreamSocket* socket) {
    306   if (result != net::OK) {
    307     callback.Run(result, NULL);
    308     return;
    309   }
    310   AdbClientSocket::HttpQuery(socket, request, callback);
    311 }
    312 
    313 // AdbCountDevicesCommand -----------------------------------------------------
    314 // TODO(zvorygin): Remove this class.
    315 class AdbCountDevicesCommand : public base::RefCountedThreadSafe<
    316     AdbCountDevicesCommand, BrowserThread::DeleteOnUIThread> {
    317  public:
    318   typedef base::Callback<void(int)> Callback;
    319 
    320   AdbCountDevicesCommand(
    321       scoped_refptr<RefCountedAdbThread> adb_thread,
    322       const Callback& callback);
    323 
    324  private:
    325   friend struct BrowserThread::DeleteOnThread<
    326       BrowserThread::UI>;
    327   friend class base::DeleteHelper<AdbCountDevicesCommand>;
    328 
    329   virtual ~AdbCountDevicesCommand();
    330   void RequestAdbDeviceCount();
    331   void ReceivedAdbDeviceCount(int result, const std::string& response);
    332   void Respond(int count);
    333 
    334   scoped_refptr<RefCountedAdbThread> adb_thread_;
    335   Callback callback_;
    336 };
    337 
    338 AdbCountDevicesCommand::AdbCountDevicesCommand(
    339     scoped_refptr<RefCountedAdbThread> adb_thread,
    340     const Callback& callback)
    341     : adb_thread_(adb_thread),
    342       callback_(callback) {
    343   adb_thread_->message_loop()->PostTask(
    344       FROM_HERE, base::Bind(&AdbCountDevicesCommand::RequestAdbDeviceCount,
    345                             this));
    346 }
    347 
    348 AdbCountDevicesCommand::~AdbCountDevicesCommand() {
    349   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    350 }
    351 
    352 void AdbCountDevicesCommand::RequestAdbDeviceCount() {
    353   DCHECK_EQ(adb_thread_->message_loop(), base::MessageLoop::current());
    354   AdbClientSocket::AdbQuery(
    355       kAdbPort, kHostDevicesCommand,
    356       base::Bind(&AdbCountDevicesCommand::ReceivedAdbDeviceCount, this));
    357 }
    358 
    359 void AdbCountDevicesCommand::ReceivedAdbDeviceCount(
    360     int result,
    361     const std::string& response) {
    362   DCHECK_EQ(adb_thread_->message_loop(), base::MessageLoop::current());
    363   std::vector<std::string> serials;
    364   Tokenize(response, "\n", &serials);
    365   BrowserThread::PostTask(
    366       BrowserThread::UI, FROM_HERE,
    367       base::Bind(&AdbCountDevicesCommand::Respond, this, serials.size()));
    368 }
    369 
    370 void AdbCountDevicesCommand::Respond(int count) {
    371   callback_.Run(count);
    372 }
    373 
    374 // AndroidDeviceProvider ---------------------------------------------------
    375 
    376 AndroidDeviceProvider::AndroidDeviceProvider()
    377   : adb_thread_(RefCountedAdbThread::GetInstance()) {
    378 
    379 }
    380 
    381 AndroidDeviceProvider::~AndroidDeviceProvider() {
    382 }
    383 
    384 // static
    385 void AndroidDeviceProvider::RunCallbackOnUIThread(
    386     const QueryDevicesCallback& callback,
    387     const AndroidDevices& result) {
    388   callback.Run(result);
    389 }
    390 
    391 // static
    392 void AndroidDeviceProvider::CountDevices(bool discover_usb_devices,
    393     const base::Callback<void(int)>& callback) {
    394   if (discover_usb_devices) {
    395     AndroidUsbDevice::CountDevices(callback);
    396     return;
    397   }
    398 
    399   new AdbCountDevicesCommand(RefCountedAdbThread::GetInstance(), callback);
    400 }
    401 
    402 // static
    403 scoped_refptr<AndroidDeviceProvider>
    404     AndroidDeviceProvider::GetUsbDeviceProvider(Profile* profile) {
    405   return new UsbDeviceProvider(profile);
    406 }
    407 
    408 // static
    409 scoped_refptr<AndroidDeviceProvider>
    410     AndroidDeviceProvider::GetAdbDeviceProvider() {
    411   return new AdbDeviceProvider();
    412 }
    413