usb_device_provider.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
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/usb/usb_device_provider.h"
6
7#include "base/strings/stringprintf.h"
8#include "chrome/browser/devtools/device/adb/adb_device_info_query.h"
9#include "chrome/browser/devtools/device/usb/android_rsa.h"
10#include "chrome/browser/devtools/device/usb/android_usb_device.h"
11#include "crypto/rsa_private_key.h"
12#include "net/base/net_errors.h"
13#include "net/socket/stream_socket.h"
14
15namespace {
16
17const char kLocalAbstractCommand[] = "localabstract:%s";
18
19const int kBufferSize = 16 * 1024;
20
21void OnOpenSocket(const UsbDeviceProvider::SocketCallback& callback,
22                  net::StreamSocket* socket,
23                  int result) {
24  callback.Run(result, result == net::OK ? socket : NULL);
25}
26
27void OnRead(net::StreamSocket* socket,
28            scoped_refptr<net::IOBuffer> buffer,
29            const std::string& data,
30            const UsbDeviceProvider::CommandCallback& callback,
31            int result) {
32  if (result <= 0) {
33    callback.Run(result, result == 0 ? data : std::string());
34    delete socket;
35    return;
36  }
37
38  std::string new_data = data + std::string(buffer->data(), result);
39  result =
40      socket->Read(buffer,
41                   kBufferSize,
42                   base::Bind(&OnRead, socket, buffer, new_data, callback));
43  if (result != net::ERR_IO_PENDING)
44    OnRead(socket, buffer, new_data, callback, result);
45}
46
47void OpenedForCommand(const UsbDeviceProvider::CommandCallback& callback,
48                      net::StreamSocket* socket,
49                      int result) {
50  if (result != net::OK) {
51    callback.Run(result, std::string());
52    return;
53  }
54  scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kBufferSize);
55  result = socket->Read(
56      buffer,
57      kBufferSize,
58      base::Bind(&OnRead, socket, buffer, std::string(), callback));
59  if (result != net::ERR_IO_PENDING)
60    OnRead(socket, buffer, std::string(), callback, result);
61}
62
63void RunCommand(scoped_refptr<AndroidUsbDevice> device,
64                const std::string& command,
65                const UsbDeviceProvider::CommandCallback& callback) {
66  net::StreamSocket* socket = device->CreateSocket(command);
67  if (!socket) {
68    callback.Run(net::ERR_CONNECTION_FAILED, std::string());
69    return;
70  }
71  int result = socket->Connect(base::Bind(&OpenedForCommand, callback, socket));
72  if (result != net::ERR_IO_PENDING)
73    callback.Run(result, std::string());
74}
75
76} // namespace
77
78// static
79void UsbDeviceProvider::CountDevices(
80    const base::Callback<void(int)>& callback) {
81  AndroidUsbDevice::CountDevices(callback);
82}
83
84UsbDeviceProvider::UsbDeviceProvider(Profile* profile){
85  rsa_key_.reset(AndroidRSAPrivateKey(profile));
86}
87
88void UsbDeviceProvider::QueryDevices(const SerialsCallback& callback) {
89  AndroidUsbDevice::Enumerate(
90      rsa_key_.get(),
91      base::Bind(&UsbDeviceProvider::EnumeratedDevices, this, callback));
92}
93
94void UsbDeviceProvider::QueryDeviceInfo(const std::string& serial,
95                                        const DeviceInfoCallback& callback) {
96  UsbDeviceMap::iterator it = device_map_.find(serial);
97  if (it == device_map_.end() || !it->second->is_connected()) {
98    AndroidDeviceManager::DeviceInfo offline_info;
99    callback.Run(offline_info);
100    return;
101  }
102  AdbDeviceInfoQuery::Start(base::Bind(&RunCommand, it->second), callback);
103}
104
105void UsbDeviceProvider::OpenSocket(const std::string& serial,
106                                   const std::string& name,
107                                   const SocketCallback& callback) {
108  UsbDeviceMap::iterator it = device_map_.find(serial);
109  if (it == device_map_.end()) {
110    callback.Run(net::ERR_CONNECTION_FAILED, NULL);
111    return;
112  }
113  std::string socket_name =
114      base::StringPrintf(kLocalAbstractCommand, name.c_str());
115  net::StreamSocket* socket = it->second->CreateSocket(socket_name);
116  if (!socket) {
117    callback.Run(net::ERR_CONNECTION_FAILED, NULL);
118    return;
119  }
120  int result = socket->Connect(base::Bind(&OnOpenSocket, callback, socket));
121  if (result != net::ERR_IO_PENDING)
122    callback.Run(result, NULL);
123}
124
125void UsbDeviceProvider::ReleaseDevice(const std::string& serial) {
126  device_map_.erase(serial);
127}
128
129UsbDeviceProvider::~UsbDeviceProvider() {
130}
131
132void UsbDeviceProvider::EnumeratedDevices(const SerialsCallback& callback,
133                                          const AndroidUsbDevices& devices) {
134  std::vector<std::string> result;
135  device_map_.clear();
136  for (AndroidUsbDevices::const_iterator it = devices.begin();
137       it != devices.end(); ++it) {
138    result.push_back((*it)->serial());
139    device_map_[(*it)->serial()] = *it;
140    (*it)->InitOnCallerThread();
141  }
142  callback.Run(result);
143}
144
145