Chromium Code Reviews| Index: chrome/browser/devtools/adb/android_usb_device.cc |
| diff --git a/chrome/browser/devtools/adb/android_usb_device.cc b/chrome/browser/devtools/adb/android_usb_device.cc |
| index 17ae407eaeb4647e65b59877d4ad4f06f17cc67e..4d99b8f3e61b7b56c3cce8e058b74590151e8947 100644 |
| --- a/chrome/browser/devtools/adb/android_usb_device.cc |
| +++ b/chrome/browser/devtools/adb/android_usb_device.cc |
| @@ -4,7 +4,10 @@ |
| #include "chrome/browser/devtools/adb/android_usb_device.h" |
| +#include <set> |
| + |
| #include "base/base64.h" |
| +#include "base/lazy_instance.h" |
| #include "base/message_loop/message_loop.h" |
| #include "base/strings/stringprintf.h" |
| #include "chrome/browser/devtools/adb/android_rsa.h" |
| @@ -12,6 +15,7 @@ |
| #include "chrome/browser/usb/usb_interface.h" |
| #include "chrome/browser/usb/usb_service.h" |
| #include "chrome/browser/usb/usb_service_factory.h" |
| +#include "crypto/rsa_private_key.h" |
| #include "net/base/ip_endpoint.h" |
| #include "net/base/net_errors.h" |
| #include "net/socket/stream_socket.h" |
| @@ -34,6 +38,11 @@ const uint32 kVersion = 0x01000000; |
| static const char kHostConnectMessage[] = "host::"; |
| +typedef std::vector<scoped_refptr<UsbDevice> > UsbDevices; |
| + |
| +base::LazyInstance<AndroidUsbDevices>::Leaky g_devices = |
| + LAZY_INSTANCE_INITIALIZER; |
| + |
| static std::string ReadSerialNumSync(libusb_device_handle* handle) { |
| libusb_device* device = libusb_get_device(handle); |
| libusb_device_descriptor descriptor; |
| @@ -84,28 +93,28 @@ static std::string ReadSerialNumSync(libusb_device_handle* handle) { |
| return std::string(); |
| } |
| -static void InterfaceClaimed(Profile* profile, |
| +static void InterfaceClaimed(crypto::RSAPrivateKey* rsa_key, |
| scoped_refptr<UsbDevice> usb_device, |
| int inbound_address, |
| int outbound_address, |
| int zero_mask, |
| - AndroidUsbDevice::Devices* devices, |
| + AndroidUsbDevices* devices, |
| bool success) { |
| if (!success) |
| return; |
| std::string serial = ReadSerialNumSync(usb_device->handle()); |
| scoped_refptr<AndroidUsbDevice> device = |
| - new AndroidUsbDevice(profile, usb_device, serial, inbound_address, |
| + new AndroidUsbDevice(rsa_key, usb_device, serial, inbound_address, |
| outbound_address, zero_mask); |
| devices->push_back(device); |
| } |
| static void ClaimInterface( |
| - Profile* profile, |
| + crypto::RSAPrivateKey* rsa_key, |
| scoped_refptr<UsbDevice> usb_device, |
| const UsbInterface* interface, |
| - AndroidUsbDevice::Devices* devices) { |
| + AndroidUsbDevices* devices) { |
| if (interface->GetNumAltSettings() == 0) |
| return; |
| @@ -138,10 +147,10 @@ static void ClaimInterface( |
| if (inbound_address == 0 || outbound_address == 0) |
| return; |
| - usb_device->ClaimInterface(1, base::Bind(&InterfaceClaimed, profile, |
| - usb_device, inbound_address, |
| - outbound_address, zero_mask, |
| - devices)); |
| + usb_device->ClaimInterface(1, base::Bind(&InterfaceClaimed, |
| + rsa_key, usb_device, |
| + inbound_address, outbound_address, |
| + zero_mask, devices)); |
| } |
| static uint32 Checksum(const std::string& data) { |
| @@ -198,32 +207,61 @@ AdbMessage::~AdbMessage() { |
| } |
| // static |
| -void AndroidUsbDevice::Enumerate(Profile* profile, Devices* devices) { |
| +void AndroidUsbDevice::Enumerate(Profile* profile, |
| + crypto::RSAPrivateKey* rsa_key, |
| + AndroidUsbDevices* devices) { |
| UsbService* service = |
| UsbServiceFactory::GetInstance()->GetForProfile(profile); |
| - |
| - // Enumerate usb devices. |
| std::vector<scoped_refptr<UsbDevice> > usb_devices; |
|
vsevik
2013/07/11 15:59:54
UsbDevices
pfeldman
2013/07/11 16:26:51
Done.
|
| service->EnumerateDevices(&usb_devices); |
| - for (size_t i = 0; i < usb_devices.size(); ++i) { |
| - scoped_refptr<UsbDevice> usb_device = usb_devices[i]; |
| - // Enumerate device interfaces. |
| + // GC Android devices with no actual usb device. |
| + AndroidUsbDevices::iterator it = g_devices.Get().begin(); |
| + std::set<UsbDevice*> claimed_devices; |
| + while (it != g_devices.Get().end()) { |
| + bool found_device = false; |
| + for (UsbDevices::iterator it2 = usb_devices.begin(); |
| + it2 != usb_devices.end() && !found_device; ++it2) { |
| + UsbDevice* usb_device = it2->get(); |
| + AndroidUsbDevice* device = it->get(); |
| + if (usb_device == device->usb_device_) { |
| + found_device = true; |
| + claimed_devices.insert(*it2); |
| + } |
| + } |
| + |
| + if (!found_device) |
| + it = g_devices.Get().erase(it); |
| + else |
| + ++it; |
| + } |
| + |
| + // Add new devices. |
| + AndroidUsbDevices new_devices; |
| + for (UsbDevices::iterator it = usb_devices.begin(); it != usb_devices.end(); |
| + ++it) { |
| + UsbDevice* usb_device = *it; |
| + if (claimed_devices.find(usb_device) != claimed_devices.end()) |
| + continue; |
| scoped_refptr<UsbConfigDescriptor> config = new UsbConfigDescriptor(); |
| usb_device->ListInterfaces(config.get(), base::Bind(&BoolNoop)); |
| - for (size_t i = 0; i < config->GetNumInterfaces(); ++i) |
| - ClaimInterface(profile, usb_device, config->GetInterface(i), devices); |
| + for (size_t j = 0; j < config->GetNumInterfaces(); ++j) { |
| + ClaimInterface(rsa_key, usb_device, config->GetInterface(j), |
| + &g_devices.Get()); |
| + } |
| } |
| + |
| + *devices = g_devices.Get(); |
| } |
| -AndroidUsbDevice::AndroidUsbDevice(Profile* profile, |
| +AndroidUsbDevice::AndroidUsbDevice(crypto::RSAPrivateKey* rsa_key, |
| scoped_refptr<UsbDevice> usb_device, |
| const std::string& serial, |
| int inbound_address, |
| int outbound_address, |
| int zero_mask) |
| : message_loop_(NULL), |
| - profile_(profile), |
| + rsa_key_(rsa_key->Copy()), |
| usb_device_(usb_device), |
| serial_(serial), |
| inbound_address_(inbound_address), |
| @@ -231,7 +269,8 @@ AndroidUsbDevice::AndroidUsbDevice(Profile* profile, |
| zero_mask_(zero_mask), |
| is_connected_(false), |
| signature_sent_(false), |
| - last_socket_id_(256) { |
| + last_socket_id_(256), |
| + terminated_(false) { |
| message_loop_ = base::MessageLoop::current(); |
| Queue(new AdbMessage(AdbMessage::kCommandCNXN, kVersion, kMaxPayload, |
| kHostConnectMessage)); |
| @@ -414,10 +453,10 @@ void AndroidUsbDevice::HandleIncoming(scoped_refptr<AdbMessage> message) { |
| if (signature_sent_) { |
| Queue(new AdbMessage(AdbMessage::kCommandAUTH, |
| AdbMessage::kAuthRSAPublicKey, 0, |
| - AndroidRSAPublicKey(profile_))); |
| + AndroidRSAPublicKey(rsa_key_.get()))); |
| } else { |
| signature_sent_ = true; |
| - std::string signature = AndroidRSASign(profile_, message->body); |
| + std::string signature = AndroidRSASign(rsa_key_.get(), message->body); |
| if (!signature.empty()) { |
| Queue(new AdbMessage(AdbMessage::kCommandAUTH, |
| AdbMessage::kAuthSignature, 0, |
| @@ -425,7 +464,7 @@ void AndroidUsbDevice::HandleIncoming(scoped_refptr<AdbMessage> message) { |
| } else { |
| Queue(new AdbMessage(AdbMessage::kCommandAUTH, |
| AdbMessage::kAuthRSAPublicKey, 0, |
| - AndroidRSAPublicKey(profile_))); |
| + AndroidRSAPublicKey(rsa_key_.get()))); |
| } |
| } |
| } |
| @@ -464,10 +503,15 @@ void AndroidUsbDevice::TransferError(UsbTransferStatus status) { |
| } |
| void AndroidUsbDevice::Terminate() { |
| + if (terminated_) |
| + return; |
| + |
| + terminated_ = true; |
| for (AndroidUsbSockets::iterator it = sockets_.begin(); |
| it != sockets_.end(); ++it) { |
| it->second->Terminated(); |
| } |
| + |
| usb_device_->ReleaseInterface(1, base::Bind(&BoolNoop)); |
| usb_device_->Close(base::Bind(&Noop)); |
| } |