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.
5 #include "chrome/browser/devtools/device/usb/usb_device_provider.h"
7 #include "base/strings/stringprintf.h"
8 #include "chrome/browser/devtools/device/usb/android_rsa.h"
9 #include "chrome/browser/devtools/device/usb/android_usb_device.h"
10 #include "crypto/rsa_private_key.h"
11 #include "net/base/net_errors.h"
12 #include "net/socket/stream_socket.h"
16 const char kLocalAbstractCommand[] = "localabstract:%s";
18 const int kBufferSize = 16 * 1024;
20 class UsbDeviceImpl : public AndroidDeviceManager::Device {
22 explicit UsbDeviceImpl(AndroidUsbDevice* device);
24 virtual void RunCommand(const std::string& command,
25 const CommandCallback& callback) OVERRIDE;
27 virtual void OpenSocket(const std::string& name,
28 const SocketCallback& callback) OVERRIDE;
30 void OnOpenSocket(const SocketCallback& callback,
31 net::StreamSocket* socket,
33 void OpenedForCommand(const CommandCallback& callback,
34 net::StreamSocket* socket,
36 void OnRead(net::StreamSocket* socket,
37 scoped_refptr<net::IOBuffer> buffer,
38 const std::string& data,
39 const CommandCallback& callback,
42 virtual ~UsbDeviceImpl() {}
43 scoped_refptr<AndroidUsbDevice> device_;
47 UsbDeviceImpl::UsbDeviceImpl(AndroidUsbDevice* device)
48 : Device(device->serial(), device->is_connected()),
50 device_->InitOnCallerThread();
53 void UsbDeviceImpl::RunCommand(const std::string& command,
54 const CommandCallback& callback) {
55 DCHECK(CalledOnValidThread());
56 net::StreamSocket* socket = device_->CreateSocket(command);
58 callback.Run(net::ERR_CONNECTION_FAILED, std::string());
61 int result = socket->Connect(base::Bind(&UsbDeviceImpl::OpenedForCommand,
62 this, callback, socket));
63 if (result != net::ERR_IO_PENDING)
64 callback.Run(result, std::string());
67 void UsbDeviceImpl::OpenSocket(const std::string& name,
68 const SocketCallback& callback) {
69 DCHECK(CalledOnValidThread());
70 std::string socket_name =
71 base::StringPrintf(kLocalAbstractCommand, name.c_str());
72 net::StreamSocket* socket = device_->CreateSocket(socket_name);
74 callback.Run(net::ERR_CONNECTION_FAILED, NULL);
77 int result = socket->Connect(base::Bind(&UsbDeviceImpl::OnOpenSocket, this,
79 if (result != net::ERR_IO_PENDING)
80 callback.Run(result, NULL);
83 void UsbDeviceImpl::OnOpenSocket(const SocketCallback& callback,
84 net::StreamSocket* socket,
86 callback.Run(result, result == net::OK ? socket : NULL);
89 void UsbDeviceImpl::OpenedForCommand(const CommandCallback& callback,
90 net::StreamSocket* socket,
92 if (result != net::OK) {
93 callback.Run(result, std::string());
96 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kBufferSize);
97 result = socket->Read(buffer, kBufferSize,
98 base::Bind(&UsbDeviceImpl::OnRead, this,
99 socket, buffer, std::string(), callback));
100 if (result != net::ERR_IO_PENDING)
101 OnRead(socket, buffer, std::string(), callback, result);
104 void UsbDeviceImpl::OnRead(net::StreamSocket* socket,
105 scoped_refptr<net::IOBuffer> buffer,
106 const std::string& data,
107 const CommandCallback& callback,
110 callback.Run(result, result == 0 ? data : std::string());
115 std::string new_data = data + std::string(buffer->data(), result);
116 result = socket->Read(buffer, kBufferSize,
117 base::Bind(&UsbDeviceImpl::OnRead, this,
118 socket, buffer, new_data, callback));
119 if (result != net::ERR_IO_PENDING)
120 OnRead(socket, buffer, new_data, callback, result);
123 static void EnumeratedDevices(
124 const UsbDeviceProvider::QueryDevicesCallback& callback,
125 const AndroidUsbDevices& devices) {
126 AndroidDeviceManager::Devices result;
127 for (AndroidUsbDevices::const_iterator it = devices.begin();
128 it != devices.end(); ++it)
129 result.push_back(new UsbDeviceImpl(*it));
130 callback.Run(result);
136 void UsbDeviceProvider::CountDevices(
137 const base::Callback<void(int)>& callback) {
138 AndroidUsbDevice::CountDevices(callback);
141 UsbDeviceProvider::UsbDeviceProvider(Profile* profile){
142 rsa_key_.reset(AndroidRSAPrivateKey(profile));
145 UsbDeviceProvider::~UsbDeviceProvider() {
148 void UsbDeviceProvider::QueryDevices(const QueryDevicesCallback& callback) {
149 AndroidUsbDevice::Enumerate(
150 rsa_key_.get(), base::Bind(&EnumeratedDevices, callback));