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