Commit 7f46b8f4 authored by pfeldman@chromium.org's avatar pfeldman@chromium.org

DevTools: request usb permission on ChromeOS.

Review URL: https://chromiumcodereview.appspot.com/23953002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@221460 0039d316-1c4b-4281-b951-d872f2087c98
parent 6278737c
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <set> #include <set>
#include "base/barrier_closure.h"
#include "base/base64.h" #include "base/base64.h"
#include "base/lazy_instance.h" #include "base/lazy_instance.h"
#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop.h"
...@@ -41,17 +42,15 @@ static const char kHostConnectMessage[] = "host::"; ...@@ -41,17 +42,15 @@ static const char kHostConnectMessage[] = "host::";
using content::BrowserThread; using content::BrowserThread;
typedef std::vector<scoped_refptr<UsbDevice> > UsbDevices; typedef std::vector<scoped_refptr<UsbDevice> > UsbDevices;
typedef std::set<scoped_refptr<UsbDevice> > UsbDeviceSet;
base::LazyInstance<AndroidUsbDevices>::Leaky g_devices = base::LazyInstance<AndroidUsbDevices>::Leaky g_devices =
LAZY_INSTANCE_INITIALIZER; LAZY_INSTANCE_INITIALIZER;
scoped_refptr<AndroidUsbDevice> ClaimInterface( bool IsAndroidInterface(
crypto::RSAPrivateKey* rsa_key, scoped_refptr<const UsbInterfaceDescriptor> interface) {
scoped_refptr<UsbDeviceHandle> usb_device,
scoped_refptr<const UsbInterfaceDescriptor> interface,
int interface_id) {
if (interface->GetNumAltSettings() == 0) if (interface->GetNumAltSettings() == 0)
return NULL; return false;
scoped_refptr<const UsbInterfaceAltSettingDescriptor> idesc = scoped_refptr<const UsbInterfaceAltSettingDescriptor> idesc =
interface->GetAltSetting(0); interface->GetAltSetting(0);
...@@ -60,8 +59,18 @@ scoped_refptr<AndroidUsbDevice> ClaimInterface( ...@@ -60,8 +59,18 @@ scoped_refptr<AndroidUsbDevice> ClaimInterface(
idesc->GetInterfaceSubclass() != kAdbSubclass || idesc->GetInterfaceSubclass() != kAdbSubclass ||
idesc->GetInterfaceProtocol() != kAdbProtocol || idesc->GetInterfaceProtocol() != kAdbProtocol ||
idesc->GetNumEndpoints() != 2) { idesc->GetNumEndpoints() != 2) {
return NULL; return false;
} }
return true;
}
scoped_refptr<AndroidUsbDevice> ClaimInterface(
crypto::RSAPrivateKey* rsa_key,
scoped_refptr<UsbDeviceHandle> usb_handle,
scoped_refptr<const UsbInterfaceDescriptor> interface,
int interface_id) {
scoped_refptr<const UsbInterfaceAltSettingDescriptor> idesc =
interface->GetAltSetting(0);
int inbound_address = 0; int inbound_address = 0;
int outbound_address = 0; int outbound_address = 0;
...@@ -82,14 +91,14 @@ scoped_refptr<AndroidUsbDevice> ClaimInterface( ...@@ -82,14 +91,14 @@ scoped_refptr<AndroidUsbDevice> ClaimInterface(
if (inbound_address == 0 || outbound_address == 0) if (inbound_address == 0 || outbound_address == 0)
return NULL; return NULL;
if (!usb_device->ClaimInterface(interface_id)) if (!usb_handle->ClaimInterface(interface_id))
return NULL; return NULL;
base::string16 serial; base::string16 serial;
if (!usb_device->GetSerial(&serial) || serial.empty()) if (!usb_handle->GetSerial(&serial) || serial.empty())
return NULL; return NULL;
return new AndroidUsbDevice(rsa_key, usb_device, UTF16ToASCII(serial), return new AndroidUsbDevice(rsa_key, usb_handle, UTF16ToASCII(serial),
inbound_address, outbound_address, zero_mask); inbound_address, outbound_address, zero_mask);
} }
...@@ -151,19 +160,56 @@ AdbMessage::AdbMessage(uint32 command, ...@@ -151,19 +160,56 @@ AdbMessage::AdbMessage(uint32 command,
AdbMessage::~AdbMessage() { AdbMessage::~AdbMessage() {
} }
static void RespondOnUIThread(const AndroidUsbDevicesCallback& callback,
const AndroidUsbDevices& devices) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
callback.Run(devices);
}
static void RespondOnFileThread(const AndroidUsbDevicesCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
// Copy g_devices.Get() on file thread.
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&RespondOnUIThread, callback, g_devices.Get()));
}
static void OpenAndroidDevicesOnFileThread(
crypto::RSAPrivateKey* rsa_key,
const base::Closure& barrier,
scoped_refptr<UsbDevice> device,
int interface_id,
bool success) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
if (success) {
scoped_refptr<UsbConfigDescriptor> config = device->ListInterfaces();
scoped_refptr<UsbDeviceHandle> usb_handle = device->Open();
if (usb_handle) {
scoped_refptr<AndroidUsbDevice> device =
ClaimInterface(rsa_key, usb_handle, config->GetInterface(interface_id),
interface_id);
if (device.get())
g_devices.Get().push_back(device);
else
usb_handle->Close();
}
}
barrier.Run();
}
static void EnumerateOnFileThread(crypto::RSAPrivateKey* rsa_key, static void EnumerateOnFileThread(crypto::RSAPrivateKey* rsa_key,
AndroidUsbDevices* result) { const AndroidUsbDevicesCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
UsbService* service = UsbService::GetInstance(); UsbService* service = UsbService::GetInstance();
AndroidUsbDevices& devices = g_devices.Get();
UsbDevices usb_devices; UsbDevices usb_devices;
service->GetDevices(&usb_devices); service->GetDevices(&usb_devices);
AndroidUsbDevices& devices = g_devices.Get();
// GC Android devices with no actual usb device. // GC Android devices with no actual usb device.
AndroidUsbDevices::iterator it = devices.begin(); AndroidUsbDevices::iterator it = devices.begin();
std::set<UsbDevice*> claimed_devices; UsbDeviceSet claimed_devices;
while (it != devices.end()) { while (it != devices.end()) {
bool found_device = false; bool found_device = false;
for (UsbDevices::iterator it2 = usb_devices.begin(); for (UsbDevices::iterator it2 = usb_devices.begin();
...@@ -183,54 +229,50 @@ static void EnumerateOnFileThread(crypto::RSAPrivateKey* rsa_key, ...@@ -183,54 +229,50 @@ static void EnumerateOnFileThread(crypto::RSAPrivateKey* rsa_key,
} }
// Add new devices. // Add new devices.
base::Closure barrier = base::BarrierClosure(
usb_devices.size(), base::Bind(&RespondOnFileThread, callback));
for (UsbDevices::iterator it = usb_devices.begin(); it != usb_devices.end(); for (UsbDevices::iterator it = usb_devices.begin(); it != usb_devices.end();
++it) { ++it) {
if (ContainsKey(claimed_devices, it->get())) if (ContainsKey(claimed_devices, it->get())) {
barrier.Run();
continue; continue;
}
scoped_refptr<UsbConfigDescriptor> config = (*it)->ListInterfaces(); scoped_refptr<UsbConfigDescriptor> config = (*it)->ListInterfaces();
if (!config) if (!config) {
continue; barrier.Run();
scoped_refptr<UsbDeviceHandle> usb_device = (*it)->Open();
if (!usb_device)
continue; continue;
}
bool claimed = false; bool has_android_interface = false;
for (size_t j = 0; j < config->GetNumInterfaces(); ++j) { for (size_t j = 0; j < config->GetNumInterfaces(); ++j) {
scoped_refptr<AndroidUsbDevice> device = if (!IsAndroidInterface(config->GetInterface(j)))
ClaimInterface(rsa_key, usb_device, config->GetInterface(j), j); continue;
if (device.get()) {
devices.push_back(device);
claimed = true;
}
}
if (!claimed)
usb_device->Close();
}
*result = devices; // Request permission on Chrome OS.
} #if defined(OS_CHROMEOS)
(*it)->RequestUsbAcess(j, base::Bind(&OpenAndroidDevicesOnFileThread,
rsa_key, barrier, *it, j));
#else
OpenAndroidDevicesOnFileThread(rsa_key, barrier, *it, j, true);
#endif // defined(OS_CHROMEOS)
static void InitDevicesOnCallerThread( has_android_interface = true;
AndroidUsbDevices* devices, break;
const AndroidUsbDevicesCallback& callback) { }
for (AndroidUsbDevices::iterator it = devices->begin(); it != devices->end(); if (!has_android_interface)
++it) { barrier.Run();
(*it)->InitOnCallerThread();
} }
callback.Run(*devices);
delete devices;
} }
// static // static
void AndroidUsbDevice::Enumerate(crypto::RSAPrivateKey* rsa_key, void AndroidUsbDevice::Enumerate(crypto::RSAPrivateKey* rsa_key,
const AndroidUsbDevicesCallback& callback) { const AndroidUsbDevicesCallback& callback) {
AndroidUsbDevices* devices = new AndroidUsbDevices(); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
BrowserThread::PostTaskAndReply( BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
BrowserThread::FILE, FROM_HERE, base::Bind(&EnumerateOnFileThread, rsa_key,
base::Bind(&EnumerateOnFileThread, rsa_key, devices), callback));
base::Bind(&InitDevicesOnCallerThread, devices, callback));
} }
AndroidUsbDevice::AndroidUsbDevice(crypto::RSAPrivateKey* rsa_key, AndroidUsbDevice::AndroidUsbDevice(crypto::RSAPrivateKey* rsa_key,
...@@ -283,6 +325,9 @@ void AndroidUsbDevice::Send(uint32 command, ...@@ -283,6 +325,9 @@ void AndroidUsbDevice::Send(uint32 command,
AndroidUsbDevice::~AndroidUsbDevice() { AndroidUsbDevice::~AndroidUsbDevice() {
Terminate(); Terminate();
usb_device_->AddRef();
BrowserThread::ReleaseSoon(BrowserThread::FILE, FROM_HERE,
usb_device_.get());
} }
void AndroidUsbDevice::Queue(scoped_refptr<AdbMessage> message) { void AndroidUsbDevice::Queue(scoped_refptr<AdbMessage> message) {
......
...@@ -99,6 +99,7 @@ class UsbDeviceImpl : public DevToolsAdbBridge::AndroidDevice { ...@@ -99,6 +99,7 @@ class UsbDeviceImpl : public DevToolsAdbBridge::AndroidDevice {
explicit UsbDeviceImpl(AndroidUsbDevice* device) explicit UsbDeviceImpl(AndroidUsbDevice* device)
: AndroidDevice(device->serial()), : AndroidDevice(device->serial()),
device_(device) { device_(device) {
device_->InitOnCallerThread();
} }
virtual void RunCommand(const std::string& command, virtual void RunCommand(const std::string& command,
...@@ -172,13 +173,20 @@ class AdbPagesCommand : public base::RefCountedThreadSafe< ...@@ -172,13 +173,20 @@ class AdbPagesCommand : public base::RefCountedThreadSafe<
public: public:
typedef base::Callback<void(DevToolsAdbBridge::RemoteDevices*)> Callback; typedef base::Callback<void(DevToolsAdbBridge::RemoteDevices*)> Callback;
AdbPagesCommand(DevToolsAdbBridge* bridge, const Callback& callback) AdbPagesCommand(DevToolsAdbBridge* bridge,
crypto::RSAPrivateKey* rsa_key,
const Callback& callback)
: bridge_(bridge), : bridge_(bridge),
callback_(callback) { callback_(callback) {
remote_devices_.reset(new DevToolsAdbBridge::RemoteDevices()); remote_devices_.reset(new DevToolsAdbBridge::RemoteDevices());
bridge_->GetAdbMessageLoop()->PostTask(FROM_HERE,
base::Bind(&DevToolsAdbBridge::EnumerateUsbDevices, bridge_, if (CommandLine::ForCurrentProcess()->HasSwitch(
base::Bind(&AdbPagesCommand::ReceivedUsbDevices, this))); switches::kRemoteDebuggingRawUSB)) {
AndroidUsbDevice::Enumerate(rsa_key,
base::Bind(&AdbPagesCommand::ReceivedUsbDevices, this));
} else {
ReceivedUsbDevices(AndroidUsbDevices());
}
} }
private: private:
...@@ -190,15 +198,41 @@ class AdbPagesCommand : public base::RefCountedThreadSafe< ...@@ -190,15 +198,41 @@ class AdbPagesCommand : public base::RefCountedThreadSafe<
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
} }
void ReceivedUsbDevices(const AndroidDevices& devices) { void ReceivedUsbDevices(const AndroidUsbDevices& usb_devices) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
bridge_->GetAdbMessageLoop()->PostTask(
FROM_HERE, base::Bind(&AdbPagesCommand::WrapUsbDevices, this,
usb_devices));
}
void WrapUsbDevices(const AndroidUsbDevices& usb_devices) {
DCHECK_EQ(bridge_->GetAdbMessageLoop(), base::MessageLoop::current()); DCHECK_EQ(bridge_->GetAdbMessageLoop(), base::MessageLoop::current());
devices_ = devices;
bridge_->EnumerateAdbDevices( #if defined(DEBUG_DEVTOOLS)
devices_.push_back(new AdbDeviceImpl("")); // For desktop remote debugging.
#endif // defined(DEBUG_DEVTOOLS)
for (AndroidUsbDevices::const_iterator it = usb_devices.begin();
it != usb_devices.end(); ++it) {
devices_.push_back(new UsbDeviceImpl(*it));
}
AdbClientSocket::AdbQuery(
kAdbPort, kHostDevicesCommand,
base::Bind(&AdbPagesCommand::ReceivedAdbDevices, this)); base::Bind(&AdbPagesCommand::ReceivedAdbDevices, this));
} }
void ReceivedAdbDevices(const AndroidDevices& devices) { void ReceivedAdbDevices(
devices_.insert(devices_.end(), devices.begin(), devices.end()); int result,
const std::string& response) {
DCHECK_EQ(bridge_->GetAdbMessageLoop(), base::MessageLoop::current());
std::vector<std::string> serials;
Tokenize(response, "\n", &serials);
for (size_t i = 0; i < serials.size(); ++i) {
std::vector<std::string> tokens;
Tokenize(serials[i], "\t ", &tokens);
devices_.push_back(new AdbDeviceImpl(tokens[0]));
}
ProcessSerials(); ProcessSerials();
} }
...@@ -868,27 +902,6 @@ DevToolsAdbBridge::DevToolsAdbBridge(Profile* profile) ...@@ -868,27 +902,6 @@ DevToolsAdbBridge::DevToolsAdbBridge(Profile* profile)
new PortForwardingController(this, profile->GetPrefs())); new PortForwardingController(this, profile->GetPrefs()));
} }
void DevToolsAdbBridge::EnumerateUsbDevices(
const AndroidDevicesCallback& callback) {
DCHECK_EQ(base::MessageLoop::current(), adb_thread_->message_loop());
if (CommandLine::ForCurrentProcess()->HasSwitch(
switches::kRemoteDebuggingRawUSB)) {
AndroidUsbDevice::Enumerate(rsa_key_.get(),
base::Bind(&DevToolsAdbBridge::ReceivedUsbDevices, this, callback));
} else {
ReceivedUsbDevices(callback, AndroidUsbDevices());
}
}
void DevToolsAdbBridge::EnumerateAdbDevices(
const AndroidDevicesCallback& callback) {
DCHECK_EQ(base::MessageLoop::current(), adb_thread_->message_loop());
AdbClientSocket::AdbQuery(
kAdbPort, kHostDevicesCommand,
base::Bind(&DevToolsAdbBridge::ReceivedAdbDevices, this, callback));
}
void DevToolsAdbBridge::AddListener(Listener* listener) { void DevToolsAdbBridge::AddListener(Listener* listener) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (listeners_.empty()) if (listeners_.empty())
...@@ -913,50 +926,14 @@ DevToolsAdbBridge::~DevToolsAdbBridge() { ...@@ -913,50 +926,14 @@ DevToolsAdbBridge::~DevToolsAdbBridge() {
DCHECK(listeners_.empty()); DCHECK(listeners_.empty());
} }
void DevToolsAdbBridge::ReceivedUsbDevices(
const AndroidDevicesCallback& callback,
const AndroidUsbDevices& usb_devices) {
AndroidDevices devices;
#if defined(DEBUG_DEVTOOLS)
devices.push_back(new AdbDeviceImpl("")); // For desktop remote debugging.
#endif // defined(DEBUG_DEVTOOLS)
for (AndroidUsbDevices::const_iterator it = usb_devices.begin();
it != usb_devices.end(); ++it) {
devices.push_back(new UsbDeviceImpl(*it));
}
callback.Run(devices);
}
void DevToolsAdbBridge::ReceivedAdbDevices(
const AndroidDevicesCallback& callback,
int result,
const std::string& response) {
AndroidDevices devices;
if (result != net::OK) {
callback.Run(devices);
return;
}
std::vector<std::string> serials;
Tokenize(response, "\n", &serials);
for (size_t i = 0; i < serials.size(); ++i) {
std::vector<std::string> tokens;
Tokenize(serials[i], "\t ", &tokens);
devices.push_back(new AdbDeviceImpl(tokens[0]));
}
callback.Run(devices);
}
void DevToolsAdbBridge::RequestRemoteDevices() { void DevToolsAdbBridge::RequestRemoteDevices() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!has_message_loop_) if (!has_message_loop_)
return; return;
new AdbPagesCommand( new AdbPagesCommand(
this, base::Bind(&DevToolsAdbBridge::ReceivedRemoteDevices, this)); this, rsa_key_.get(),
base::Bind(&DevToolsAdbBridge::ReceivedRemoteDevices, this));
} }
void DevToolsAdbBridge::ReceivedRemoteDevices(RemoteDevices* devices_ptr) { void DevToolsAdbBridge::ReceivedRemoteDevices(RemoteDevices* devices_ptr) {
......
...@@ -266,9 +266,6 @@ class DevToolsAdbBridge ...@@ -266,9 +266,6 @@ class DevToolsAdbBridge
explicit DevToolsAdbBridge(Profile* profile); explicit DevToolsAdbBridge(Profile* profile);
void EnumerateUsbDevices(const AndroidDevicesCallback& callback);
void EnumerateAdbDevices(const AndroidDevicesCallback& callback);
void AddListener(Listener* listener); void AddListener(Listener* listener);
void RemoveListener(Listener* listener); void RemoveListener(Listener* listener);
...@@ -295,11 +292,6 @@ class DevToolsAdbBridge ...@@ -295,11 +292,6 @@ class DevToolsAdbBridge
}; };
virtual ~DevToolsAdbBridge(); virtual ~DevToolsAdbBridge();
void ReceivedUsbDevices(const AndroidDevicesCallback& callback,
const AndroidUsbDevices& usb_devices);
void ReceivedAdbDevices(const AndroidDevicesCallback& callback,
int result,
const std::string& response);
void RequestRemoteDevices(); void RequestRemoteDevices();
void ReceivedRemoteDevices(RemoteDevices* devices); void ReceivedRemoteDevices(RemoteDevices* devices);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment