Home | History | Annotate | Download | only in device
      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 "chrome/browser/devtools/device/android_device_manager.h"
      6 
      7 #include "base/strings/string_number_conversions.h"
      8 #include "base/strings/string_util.h"
      9 #include "base/strings/stringprintf.h"
     10 #include "net/base/io_buffer.h"
     11 #include "net/base/net_errors.h"
     12 #include "net/socket/stream_socket.h"
     13 
     14 using content::BrowserThread;
     15 
     16 namespace {
     17 
     18 const char kDevToolsAdbBridgeThreadName[] = "Chrome_DevToolsADBThread";
     19 
     20 const int kBufferSize = 16 * 1024;
     21 
     22 static const char kModelOffline[] = "Offline";
     23 
     24 static const char kHttpGetRequest[] = "GET %s HTTP/1.1\r\n\r\n";
     25 
     26 static const char kWebSocketUpgradeRequest[] = "GET %s HTTP/1.1\r\n"
     27     "Upgrade: WebSocket\r\n"
     28     "Connection: Upgrade\r\n"
     29     "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
     30     "Sec-WebSocket-Version: 13\r\n"
     31     "\r\n";
     32 
     33 static void PostDeviceInfoCallback(
     34     scoped_refptr<base::MessageLoopProxy> response_message_loop,
     35     const AndroidDeviceManager::DeviceInfoCallback& callback,
     36     const AndroidDeviceManager::DeviceInfo& device_info) {
     37   response_message_loop->PostTask(FROM_HERE, base::Bind(callback, device_info));
     38 }
     39 
     40 static void PostCommandCallback(
     41     scoped_refptr<base::MessageLoopProxy> response_message_loop,
     42     const AndroidDeviceManager::CommandCallback& callback,
     43     int result,
     44     const std::string& response) {
     45   response_message_loop->PostTask(FROM_HERE,
     46                                   base::Bind(callback, result, response));
     47 }
     48 
     49 static void PostSocketCallback(
     50     scoped_refptr<base::MessageLoopProxy> response_message_loop,
     51     const AndroidDeviceManager::SocketCallback& callback,
     52     int result,
     53     net::StreamSocket* socket) {
     54   response_message_loop->PostTask(FROM_HERE,
     55                                   base::Bind(callback, result, socket));
     56 }
     57 
     58 class HttpRequest {
     59  public:
     60   typedef AndroidDeviceManager::CommandCallback CommandCallback;
     61   typedef AndroidDeviceManager::SocketCallback SocketCallback;
     62 
     63   static void CommandRequest(const std::string& request,
     64                            const CommandCallback& callback,
     65                            int result,
     66                            net::StreamSocket* socket) {
     67     if (result != net::OK) {
     68       callback.Run(result, std::string());
     69       return;
     70     }
     71     new HttpRequest(socket, request, callback);
     72   }
     73 
     74   static void SocketRequest(const std::string& request,
     75                           const SocketCallback& callback,
     76                           int result,
     77                           net::StreamSocket* socket) {
     78     if (result != net::OK) {
     79       callback.Run(result, NULL);
     80       return;
     81     }
     82     new HttpRequest(socket, request, callback);
     83   }
     84 
     85  private:
     86   HttpRequest(net::StreamSocket* socket,
     87               const std::string& request,
     88               const CommandCallback& callback)
     89       : socket_(socket), command_callback_(callback), body_pos_(0) {
     90     SendRequest(request);
     91   }
     92 
     93   HttpRequest(net::StreamSocket* socket,
     94                       const std::string& request,
     95                       const SocketCallback& callback)
     96     : socket_(socket),
     97       socket_callback_(callback),
     98       body_pos_(0) {
     99     SendRequest(request);
    100   }
    101 
    102   ~HttpRequest() {
    103   }
    104 
    105   void SendRequest(const std::string& request) {
    106     scoped_refptr<net::StringIOBuffer> request_buffer =
    107         new net::StringIOBuffer(request);
    108 
    109     int result = socket_->Write(
    110         request_buffer.get(),
    111         request_buffer->size(),
    112         base::Bind(&HttpRequest::ReadResponse, base::Unretained(this)));
    113     if (result != net::ERR_IO_PENDING)
    114       ReadResponse(result);
    115   }
    116 
    117   void ReadResponse(int result) {
    118     if (!CheckNetResultOrDie(result))
    119       return;
    120     scoped_refptr<net::IOBuffer> response_buffer =
    121         new net::IOBuffer(kBufferSize);
    122 
    123     result = socket_->Read(
    124         response_buffer.get(),
    125         kBufferSize,
    126         base::Bind(&HttpRequest::OnResponseData, base::Unretained(this),
    127                   response_buffer,
    128                   -1));
    129     if (result != net::ERR_IO_PENDING)
    130       OnResponseData(response_buffer, -1, result);
    131   }
    132 
    133   void OnResponseData(scoped_refptr<net::IOBuffer> response_buffer,
    134                       int bytes_total,
    135                       int result) {
    136     if (!CheckNetResultOrDie(result))
    137       return;
    138     if (result == 0) {
    139       CheckNetResultOrDie(net::ERR_CONNECTION_CLOSED);
    140       return;
    141     }
    142 
    143     response_ += std::string(response_buffer->data(), result);
    144     int expected_length = 0;
    145     if (bytes_total < 0) {
    146       // TODO(kaznacheev): Use net::HttpResponseHeader to parse the header.
    147       size_t content_pos = response_.find("Content-Length:");
    148       if (content_pos != std::string::npos) {
    149         size_t endline_pos = response_.find("\n", content_pos);
    150         if (endline_pos != std::string::npos) {
    151           std::string len = response_.substr(content_pos + 15,
    152                                              endline_pos - content_pos - 15);
    153           base::TrimWhitespace(len, base::TRIM_ALL, &len);
    154           if (!base::StringToInt(len, &expected_length)) {
    155             CheckNetResultOrDie(net::ERR_FAILED);
    156             return;
    157           }
    158         }
    159       }
    160 
    161       body_pos_ = response_.find("\r\n\r\n");
    162       if (body_pos_ != std::string::npos) {
    163         body_pos_ += 4;
    164         bytes_total = body_pos_ + expected_length;
    165       }
    166     }
    167 
    168     if (bytes_total == static_cast<int>(response_.length())) {
    169       if (!command_callback_.is_null())
    170         command_callback_.Run(net::OK, response_.substr(body_pos_));
    171       else
    172         socket_callback_.Run(net::OK, socket_.release());
    173       delete this;
    174       return;
    175     }
    176 
    177     result = socket_->Read(
    178         response_buffer.get(),
    179         kBufferSize,
    180         base::Bind(&HttpRequest::OnResponseData,
    181                    base::Unretained(this),
    182                    response_buffer,
    183                    bytes_total));
    184     if (result != net::ERR_IO_PENDING)
    185       OnResponseData(response_buffer, bytes_total, result);
    186   }
    187 
    188   bool CheckNetResultOrDie(int result) {
    189     if (result >= 0)
    190       return true;
    191     if (!command_callback_.is_null())
    192       command_callback_.Run(result, std::string());
    193     else
    194       socket_callback_.Run(result, NULL);
    195     delete this;
    196     return false;
    197   }
    198 
    199   scoped_ptr<net::StreamSocket> socket_;
    200   std::string response_;
    201   AndroidDeviceManager::CommandCallback command_callback_;
    202   AndroidDeviceManager::SocketCallback socket_callback_;
    203   size_t body_pos_;
    204 };
    205 
    206 class DevicesRequest : public base::RefCountedThreadSafe<DevicesRequest> {
    207  public:
    208   typedef AndroidDeviceManager::DeviceInfo DeviceInfo;
    209   typedef AndroidDeviceManager::DeviceProvider DeviceProvider;
    210   typedef AndroidDeviceManager::DeviceProviders DeviceProviders;
    211   typedef AndroidDeviceManager::DeviceDescriptors DeviceDescriptors;
    212   typedef base::Callback<void(DeviceDescriptors*)>
    213       DescriptorsCallback;
    214 
    215   static void Start(scoped_refptr<base::MessageLoopProxy> device_message_loop,
    216                     const DeviceProviders& providers,
    217                     const DescriptorsCallback& callback) {
    218     // Don't keep counted reference on calling thread;
    219     DevicesRequest* request = new DevicesRequest(callback);
    220     // Avoid destruction while sending requests
    221     request->AddRef();
    222     for (DeviceProviders::const_iterator it = providers.begin();
    223          it != providers.end(); ++it) {
    224       device_message_loop->PostTask(
    225           FROM_HERE,
    226           base::Bind(
    227               &DeviceProvider::QueryDevices,
    228               *it,
    229               base::Bind(&DevicesRequest::ProcessSerials, request, *it)));
    230     }
    231     device_message_loop->ReleaseSoon(FROM_HERE, request);
    232   }
    233 
    234  private:
    235   explicit DevicesRequest(const DescriptorsCallback& callback)
    236       : response_message_loop_(base::MessageLoopProxy::current()),
    237         callback_(callback),
    238         descriptors_(new DeviceDescriptors()) {
    239   }
    240 
    241   friend class base::RefCountedThreadSafe<DevicesRequest>;
    242   ~DevicesRequest() {
    243     response_message_loop_->PostTask(FROM_HERE,
    244         base::Bind(callback_, descriptors_.release()));
    245   }
    246 
    247   typedef std::vector<std::string> Serials;
    248 
    249   void ProcessSerials(scoped_refptr<DeviceProvider> provider,
    250                       const Serials& serials) {
    251     for (Serials::const_iterator it = serials.begin(); it != serials.end();
    252          ++it) {
    253       descriptors_->resize(descriptors_->size() + 1);
    254       descriptors_->back().provider = provider;
    255       descriptors_->back().serial = *it;
    256     }
    257   }
    258 
    259   scoped_refptr<base::MessageLoopProxy> response_message_loop_;
    260   DescriptorsCallback callback_;
    261   scoped_ptr<DeviceDescriptors> descriptors_;
    262 };
    263 
    264 void ReleaseDeviceAndProvider(
    265     AndroidDeviceManager::DeviceProvider* provider,
    266     const std::string& serial) {
    267   provider->ReleaseDevice(serial);
    268   provider->Release();
    269 }
    270 
    271 } // namespace
    272 
    273 AndroidDeviceManager::BrowserInfo::BrowserInfo()
    274     : type(kTypeOther) {
    275 }
    276 
    277 AndroidDeviceManager::DeviceInfo::DeviceInfo()
    278     : model(kModelOffline), connected(false) {
    279 }
    280 
    281 AndroidDeviceManager::DeviceInfo::~DeviceInfo() {
    282 }
    283 
    284 AndroidDeviceManager::DeviceDescriptor::DeviceDescriptor() {
    285 }
    286 
    287 AndroidDeviceManager::DeviceDescriptor::~DeviceDescriptor() {
    288 }
    289 
    290 void AndroidDeviceManager::DeviceProvider::SendJsonRequest(
    291     const std::string& serial,
    292     const std::string& socket_name,
    293     const std::string& request,
    294     const CommandCallback& callback) {
    295   OpenSocket(serial,
    296              socket_name,
    297              base::Bind(&HttpRequest::CommandRequest,
    298                         base::StringPrintf(kHttpGetRequest, request.c_str()),
    299                         callback));
    300 }
    301 
    302 void AndroidDeviceManager::DeviceProvider::HttpUpgrade(
    303     const std::string& serial,
    304     const std::string& socket_name,
    305     const std::string& url,
    306     const SocketCallback& callback) {
    307   OpenSocket(
    308       serial,
    309       socket_name,
    310       base::Bind(&HttpRequest::SocketRequest,
    311                  base::StringPrintf(kWebSocketUpgradeRequest, url.c_str()),
    312                  callback));
    313 }
    314 
    315 void AndroidDeviceManager::DeviceProvider::ReleaseDevice(
    316     const std::string& serial) {
    317 }
    318 
    319 AndroidDeviceManager::DeviceProvider::DeviceProvider() {
    320 }
    321 
    322 AndroidDeviceManager::DeviceProvider::~DeviceProvider() {
    323 }
    324 
    325 void AndroidDeviceManager::Device::QueryDeviceInfo(
    326     const DeviceInfoCallback& callback) {
    327   device_message_loop_->PostTask(
    328       FROM_HERE,
    329       base::Bind(&DeviceProvider::QueryDeviceInfo,
    330                  provider_,
    331                  serial_,
    332                  base::Bind(&PostDeviceInfoCallback,
    333                             base::MessageLoopProxy::current(),
    334                             callback)));
    335 }
    336 
    337 void AndroidDeviceManager::Device::OpenSocket(const std::string& socket_name,
    338                                               const SocketCallback& callback) {
    339   device_message_loop_->PostTask(
    340       FROM_HERE,
    341       base::Bind(&DeviceProvider::OpenSocket,
    342                  provider_,
    343                  serial_,
    344                  socket_name,
    345                  callback));
    346 }
    347 
    348 void AndroidDeviceManager::Device::SendJsonRequest(
    349     const std::string& socket_name,
    350     const std::string& request,
    351     const CommandCallback& callback) {
    352   device_message_loop_->PostTask(
    353       FROM_HERE,
    354       base::Bind(&DeviceProvider::SendJsonRequest,
    355                  provider_,
    356                  serial_,
    357                  socket_name,
    358                  request,
    359                  base::Bind(&PostCommandCallback,
    360                             base::MessageLoopProxy::current(),
    361                             callback)));
    362 }
    363 
    364 void AndroidDeviceManager::Device::HttpUpgrade(const std::string& socket_name,
    365                                                const std::string& url,
    366                                                const SocketCallback& callback) {
    367   device_message_loop_->PostTask(
    368       FROM_HERE,
    369       base::Bind(&DeviceProvider::HttpUpgrade,
    370                  provider_,
    371                  serial_,
    372                  socket_name,
    373                  url,
    374                  base::Bind(&PostSocketCallback,
    375                             base::MessageLoopProxy::current(),
    376                             callback)));
    377 }
    378 
    379 AndroidDeviceManager::Device::Device(
    380     scoped_refptr<base::MessageLoopProxy> device_message_loop,
    381     scoped_refptr<DeviceProvider> provider,
    382     const std::string& serial)
    383     : device_message_loop_(device_message_loop),
    384       provider_(provider),
    385       serial_(serial),
    386       weak_factory_(this) {
    387 }
    388 
    389 AndroidDeviceManager::Device::~Device() {
    390   provider_->AddRef();
    391   DeviceProvider* raw_ptr = provider_.get();
    392   provider_ = NULL;
    393   device_message_loop_->PostTask(
    394       FROM_HERE,
    395       base::Bind(&ReleaseDeviceAndProvider,
    396                  base::Unretained(raw_ptr),
    397                  serial_));
    398 }
    399 
    400 AndroidDeviceManager::HandlerThread*
    401 AndroidDeviceManager::HandlerThread::instance_ = NULL;
    402 
    403 // static
    404 scoped_refptr<AndroidDeviceManager::HandlerThread>
    405 AndroidDeviceManager::HandlerThread::GetInstance() {
    406   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    407   if (!instance_)
    408     new HandlerThread();
    409   return instance_;
    410 }
    411 
    412 AndroidDeviceManager::HandlerThread::HandlerThread() {
    413   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    414   instance_ = this;
    415   thread_ = new base::Thread(kDevToolsAdbBridgeThreadName);
    416   base::Thread::Options options;
    417   options.message_loop_type = base::MessageLoop::TYPE_IO;
    418   if (!thread_->StartWithOptions(options)) {
    419     delete thread_;
    420     thread_ = NULL;
    421   }
    422 }
    423 
    424 scoped_refptr<base::MessageLoopProxy>
    425 AndroidDeviceManager::HandlerThread::message_loop() {
    426   return thread_ ? thread_->message_loop_proxy() : NULL;
    427 }
    428 
    429 // static
    430 void AndroidDeviceManager::HandlerThread::StopThread(
    431     base::Thread* thread) {
    432   thread->Stop();
    433 }
    434 
    435 AndroidDeviceManager::HandlerThread::~HandlerThread() {
    436   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    437   instance_ = NULL;
    438   if (!thread_)
    439     return;
    440   // Shut down thread on FILE thread to join into IO.
    441   content::BrowserThread::PostTask(
    442       content::BrowserThread::FILE, FROM_HERE,
    443       base::Bind(&HandlerThread::StopThread, thread_));
    444 }
    445 
    446 // static
    447 scoped_refptr<AndroidDeviceManager> AndroidDeviceManager::Create() {
    448   return new AndroidDeviceManager();
    449 }
    450 
    451 void AndroidDeviceManager::SetDeviceProviders(
    452     const DeviceProviders& providers) {
    453   for (DeviceProviders::iterator it = providers_.begin();
    454       it != providers_.end(); ++it) {
    455     (*it)->AddRef();
    456     DeviceProvider* raw_ptr = it->get();
    457     *it = NULL;
    458     handler_thread_->message_loop()->ReleaseSoon(FROM_HERE, raw_ptr);
    459   }
    460   providers_ = providers;
    461 }
    462 
    463 void AndroidDeviceManager::QueryDevices(const DevicesCallback& callback) {
    464   DevicesRequest::Start(handler_thread_->message_loop(),
    465                         providers_,
    466                         base::Bind(&AndroidDeviceManager::UpdateDevices,
    467                                    this,
    468                                    callback));
    469 }
    470 
    471 AndroidDeviceManager::AndroidDeviceManager()
    472     : handler_thread_(HandlerThread::GetInstance()) {
    473 }
    474 
    475 AndroidDeviceManager::~AndroidDeviceManager() {
    476   SetDeviceProviders(DeviceProviders());
    477 }
    478 
    479 void AndroidDeviceManager::UpdateDevices(
    480     const DevicesCallback& callback,
    481     DeviceDescriptors* descriptors_raw) {
    482   scoped_ptr<DeviceDescriptors> descriptors(descriptors_raw);
    483   Devices response;
    484   DeviceWeakMap new_devices;
    485   for (DeviceDescriptors::const_iterator it = descriptors->begin();
    486        it != descriptors->end();
    487        ++it) {
    488     DeviceWeakMap::iterator found = devices_.find(it->serial);
    489     scoped_refptr<Device> device;
    490     if (found == devices_.end() || !found->second
    491         || found->second->provider_ != it->provider) {
    492       device = new Device(handler_thread_->message_loop(),
    493           it->provider, it->serial);
    494     } else {
    495       device = found->second.get();
    496     }
    497     response.push_back(device);
    498     new_devices[it->serial] = device->weak_factory_.GetWeakPtr();
    499   }
    500   devices_.swap(new_devices);
    501   callback.Run(response);
    502 }
    503