// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/devtools/device/usb/usb_device_provider.h" #include "base/strings/stringprintf.h" #include "chrome/browser/devtools/device/adb/adb_device_info_query.h" #include "chrome/browser/devtools/device/usb/android_rsa.h" #include "chrome/browser/devtools/device/usb/android_usb_device.h" #include "crypto/rsa_private_key.h" #include "net/base/net_errors.h" #include "net/socket/stream_socket.h" namespace { const char kLocalAbstractCommand[] = "localabstract:%s"; const int kBufferSize = 16 * 1024; void OnOpenSocket(const UsbDeviceProvider::SocketCallback& callback, net::StreamSocket* socket, int result) { callback.Run(result, result == net::OK ? socket : NULL); } void OnRead(net::StreamSocket* socket, scoped_refptr buffer, const std::string& data, const UsbDeviceProvider::CommandCallback& callback, int result) { if (result <= 0) { callback.Run(result, result == 0 ? data : std::string()); delete socket; return; } std::string new_data = data + std::string(buffer->data(), result); result = socket->Read(buffer.get(), kBufferSize, base::Bind(&OnRead, socket, buffer, new_data, callback)); if (result != net::ERR_IO_PENDING) OnRead(socket, buffer, new_data, callback, result); } void OpenedForCommand(const UsbDeviceProvider::CommandCallback& callback, net::StreamSocket* socket, int result) { if (result != net::OK) { callback.Run(result, std::string()); return; } scoped_refptr buffer = new net::IOBuffer(kBufferSize); result = socket->Read( buffer.get(), kBufferSize, base::Bind(&OnRead, socket, buffer, std::string(), callback)); if (result != net::ERR_IO_PENDING) OnRead(socket, buffer, std::string(), callback, result); } void RunCommand(scoped_refptr device, const std::string& command, const UsbDeviceProvider::CommandCallback& callback) { net::StreamSocket* socket = device->CreateSocket(command); if (!socket) { callback.Run(net::ERR_CONNECTION_FAILED, std::string()); return; } int result = socket->Connect(base::Bind(&OpenedForCommand, callback, socket)); if (result != net::ERR_IO_PENDING) callback.Run(result, std::string()); } } // namespace // static void UsbDeviceProvider::CountDevices( const base::Callback& callback) { AndroidUsbDevice::CountDevices(callback); } UsbDeviceProvider::UsbDeviceProvider(Profile* profile){ rsa_key_.reset(AndroidRSAPrivateKey(profile)); } void UsbDeviceProvider::QueryDevices(const SerialsCallback& callback) { AndroidUsbDevice::Enumerate( rsa_key_.get(), base::Bind(&UsbDeviceProvider::EnumeratedDevices, this, callback)); } void UsbDeviceProvider::QueryDeviceInfo(const std::string& serial, const DeviceInfoCallback& callback) { UsbDeviceMap::iterator it = device_map_.find(serial); if (it == device_map_.end() || !it->second->is_connected()) { AndroidDeviceManager::DeviceInfo offline_info; callback.Run(offline_info); return; } AdbDeviceInfoQuery::Start(base::Bind(&RunCommand, it->second), callback); } void UsbDeviceProvider::OpenSocket(const std::string& serial, const std::string& name, const SocketCallback& callback) { UsbDeviceMap::iterator it = device_map_.find(serial); if (it == device_map_.end()) { callback.Run(net::ERR_CONNECTION_FAILED, NULL); return; } std::string socket_name = base::StringPrintf(kLocalAbstractCommand, name.c_str()); net::StreamSocket* socket = it->second->CreateSocket(socket_name); if (!socket) { callback.Run(net::ERR_CONNECTION_FAILED, NULL); return; } int result = socket->Connect(base::Bind(&OnOpenSocket, callback, socket)); if (result != net::ERR_IO_PENDING) callback.Run(result, NULL); } void UsbDeviceProvider::ReleaseDevice(const std::string& serial) { device_map_.erase(serial); } UsbDeviceProvider::~UsbDeviceProvider() { } void UsbDeviceProvider::EnumeratedDevices(const SerialsCallback& callback, const AndroidUsbDevices& devices) { std::vector result; device_map_.clear(); for (AndroidUsbDevices::const_iterator it = devices.begin(); it != devices.end(); ++it) { result.push_back((*it)->serial()); device_map_[(*it)->serial()] = *it; (*it)->InitOnCallerThread(); } callback.Run(result); }