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..5d49caceff245efcf0d9f2b40f43c78d8fa1003c 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; |
+ UsbDevices usb_devices; |
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()))); |
} |
} |
} |
@@ -457,17 +496,24 @@ void AndroidUsbDevice::HandleIncoming(scoped_refptr<AdbMessage> message) { |
} |
void AndroidUsbDevice::TransferError(UsbTransferStatus status) { |
- LOG(ERROR) << "Transfer error " << status; |
message_loop_->PostTask(FROM_HERE, |
base::Bind(&AndroidUsbDevice::Terminate, |
this)); |
} |
void AndroidUsbDevice::Terminate() { |
- for (AndroidUsbSockets::iterator it = sockets_.begin(); |
- it != sockets_.end(); ++it) { |
+ if (terminated_) |
+ return; |
+ |
+ terminated_ = true; |
+ |
+ // Iterate over copy. |
+ AndroidUsbSockets sockets(sockets_); |
+ 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)); |
} |