DevTools: Partially redesigned DevToolsAndroidBridge and AndroidDeviceManager.

Review URL: https://codereview.chromium.org/287643002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@274211 0039d316-1c4b-4281-b951-d872f2087c98
parent d9250e7f
......@@ -34,6 +34,7 @@ class AdbClientSocketTest : public InProcessBrowserTest,
device_providers.push_back(new AdbDeviceProvider());
android_bridge_->set_device_providers_for_test(device_providers);
android_bridge_->AddDeviceListListener(this);
content::RunMessageLoop();
}
virtual void DeviceListChanged(
......@@ -125,7 +126,6 @@ class AdbClientSocketTest : public InProcessBrowserTest,
IN_PROC_BROWSER_TEST_F(AdbClientSocketTest, TestAdbClientSocket) {
StartMockAdbServer();
StartTest();
content::RunMessageLoop();
CheckDevices();
StopMockAdbServer();
}
......@@ -209,6 +209,7 @@ void AdbDeviceInfoQuery::ReceivedModel(int result,
return;
}
device_info_.model = response;
device_info_.connected = true;
command_callback_.Run(
kDumpsysCommand,
base::Bind(&AdbDeviceInfoQuery::ReceivedDumpsys, base::Unretained(this)));
......
......@@ -17,68 +17,48 @@ const char kLocalAbstractCommand[] = "localabstract:%s";
const int kAdbPort = 5037;
class AdbDeviceImpl : public AndroidDeviceManager::Device {
public:
AdbDeviceImpl(const std::string& serial, bool is_connected);
virtual void QueryDeviceInfo(const DeviceInfoCallback& callback) OVERRIDE;
virtual void OpenSocket(const std::string& name,
const SocketCallback& callback) OVERRIDE;
private:
virtual ~AdbDeviceImpl() {}
void RunCommand(const std::string& command,
const CommandCallback& callback);
};
AdbDeviceImpl::AdbDeviceImpl(const std::string& serial, bool is_connected)
: Device(serial, is_connected) {
}
void AdbDeviceImpl::QueryDeviceInfo(const DeviceInfoCallback& callback) {
AdbDeviceInfoQuery::Start(
base::Bind(&AdbDeviceImpl::RunCommand, this), callback);
}
void AdbDeviceImpl::OpenSocket(const std::string& name,
const SocketCallback& callback) {
DCHECK(CalledOnValidThread());
std::string socket_name =
base::StringPrintf(kLocalAbstractCommand, name.c_str());
AdbClientSocket::TransportQuery(kAdbPort, serial(), socket_name, callback);
}
void AdbDeviceImpl::RunCommand(const std::string& command,
const CommandCallback& callback) {
DCHECK(CalledOnValidThread());
std::string query = base::StringPrintf(kHostTransportCommand,
serial().c_str(), command.c_str());
static void RunCommand(const std::string& serial,
const std::string& command,
const AdbDeviceProvider::CommandCallback& callback) {
std::string query = base::StringPrintf(
kHostTransportCommand, serial.c_str(), command.c_str());
AdbClientSocket::AdbQuery(kAdbPort, query, callback);
}
// static
void ReceivedAdbDevices(
const AdbDeviceProvider::QueryDevicesCallback& callback,
static void ReceivedAdbDevices(
const AdbDeviceProvider::SerialsCallback& callback,
int result_code,
const std::string& response) {
AndroidDeviceManager::Devices result;
std::vector<std::string> result;
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);
bool offline = tokens.size() > 1 && tokens[1] == "offline";
result.push_back(new AdbDeviceImpl(tokens[0], !offline));
result.push_back(tokens[0]);
}
callback.Run(result);
}
} // namespace
AdbDeviceProvider::~AdbDeviceProvider() {
}
void AdbDeviceProvider::QueryDevices(const QueryDevicesCallback& callback) {
void AdbDeviceProvider::QueryDevices(const SerialsCallback& callback) {
AdbClientSocket::AdbQuery(
kAdbPort, kHostDevicesCommand, base::Bind(&ReceivedAdbDevices, callback));
}
void AdbDeviceProvider::QueryDeviceInfo(const std::string& serial,
const DeviceInfoCallback& callback) {
AdbDeviceInfoQuery::Start(base::Bind(&RunCommand, serial), callback);
}
void AdbDeviceProvider::OpenSocket(const std::string& serial,
const std::string& socket_name,
const SocketCallback& callback) {
std::string request =
base::StringPrintf(kLocalAbstractCommand, socket_name.c_str());
AdbClientSocket::TransportQuery(kAdbPort, serial, request, callback);
}
AdbDeviceProvider::~AdbDeviceProvider() {
}
......@@ -9,9 +9,14 @@
class AdbDeviceProvider : public AndroidDeviceManager::DeviceProvider {
public:
typedef DeviceProvider::QueryDevicesCallback QueryDevicesCallback;
virtual void QueryDevices(const SerialsCallback& callback) OVERRIDE;
virtual void QueryDevices(const QueryDevicesCallback& callback) OVERRIDE;
virtual void QueryDeviceInfo(const std::string& serial,
const DeviceInfoCallback& callback) OVERRIDE;
virtual void OpenSocket(const std::string& serial,
const std::string& socket_name,
const SocketCallback& callback) OVERRIDE;
private:
virtual ~AdbDeviceProvider();
......
......@@ -463,7 +463,7 @@ class MockAdbServer : SingleConnectionServer::Parser,
selected_device_ = command.substr(strlen(kHostTransportPrefix));
SendResponse("");
} else if (selected_device_ != kSerialOnline) {
NOTREACHED() << "Unknown device - " << selected_device_;
Send("FAIL", "device offline (x)");
} else if (command == kDeviceModelCommand) {
SendResponse(kDeviceModel);
} else if (command == kOpenedUnixSocketsCommand) {
......@@ -480,10 +480,14 @@ class MockAdbServer : SingleConnectionServer::Parser,
}
}
void SendResponse(const std::string& response) {
void SendResponse(const std::string& response) { Send("OKAY", response); }
void Send(const std::string& status, const std::string& response) {
CHECK(CalledOnValidThread());
CHECK_EQ(4U, status.size());
std::stringstream response_stream;
response_stream << "OKAY";
response_stream << status;
int size = response.size();
if (size > 0) {
......
......@@ -11,10 +11,16 @@
#include "net/base/net_errors.h"
#include "net/socket/stream_socket.h"
using content::BrowserThread;
namespace {
const char kDevToolsAdbBridgeThreadName[] = "Chrome_DevToolsADBThread";
const int kBufferSize = 16 * 1024;
static const char kModelOffline[] = "Offline";
static const char kHttpGetRequest[] = "GET %s HTTP/1.1\r\n\r\n";
static const char kWebSocketUpgradeRequest[] = "GET %s HTTP/1.1\r\n"
......@@ -24,6 +30,31 @@ static const char kWebSocketUpgradeRequest[] = "GET %s HTTP/1.1\r\n"
"Sec-WebSocket-Version: 13\r\n"
"\r\n";
static void PostDeviceInfoCallback(
scoped_refptr<base::MessageLoopProxy> response_message_loop,
const AndroidDeviceManager::DeviceInfoCallback& callback,
const AndroidDeviceManager::DeviceInfo& device_info) {
response_message_loop->PostTask(FROM_HERE, base::Bind(callback, device_info));
}
static void PostCommandCallback(
scoped_refptr<base::MessageLoopProxy> response_message_loop,
const AndroidDeviceManager::CommandCallback& callback,
int result,
const std::string& response) {
response_message_loop->PostTask(FROM_HERE,
base::Bind(callback, result, response));
}
static void PostSocketCallback(
scoped_refptr<base::MessageLoopProxy> response_message_loop,
const AndroidDeviceManager::SocketCallback& callback,
int result,
net::StreamSocket* socket) {
response_message_loop->PostTask(FROM_HERE,
base::Bind(callback, result, socket));
}
class HttpRequest {
public:
typedef AndroidDeviceManager::CommandCallback CommandCallback;
......@@ -53,11 +84,9 @@ class HttpRequest {
private:
HttpRequest(net::StreamSocket* socket,
const std::string& request,
const CommandCallback& callback)
: socket_(socket),
command_callback_(callback),
body_pos_(0) {
const std::string& request,
const CommandCallback& callback)
: socket_(socket), command_callback_(callback), body_pos_(0) {
SendRequest(request);
}
......@@ -174,33 +203,117 @@ class HttpRequest {
size_t body_pos_;
};
class DevicesRequest : public base::RefCountedThreadSafe<DevicesRequest> {
public:
typedef AndroidDeviceManager::DeviceInfo DeviceInfo;
typedef AndroidDeviceManager::DeviceProvider DeviceProvider;
typedef AndroidDeviceManager::DeviceProviders DeviceProviders;
typedef AndroidDeviceManager::DeviceDescriptors DeviceDescriptors;
typedef base::Callback<void(DeviceDescriptors*)>
DescriptorsCallback;
static void Start(scoped_refptr<base::MessageLoopProxy> device_message_loop,
const DeviceProviders& providers,
const DescriptorsCallback& callback) {
// Don't keep counted reference on calling thread;
DevicesRequest* request = new DevicesRequest(callback);
// Avoid destruction while sending requests
request->AddRef();
for (DeviceProviders::const_iterator it = providers.begin();
it != providers.end(); ++it) {
device_message_loop->PostTask(
FROM_HERE,
base::Bind(
&DeviceProvider::QueryDevices,
*it,
base::Bind(&DevicesRequest::ProcessSerials, request, *it)));
}
device_message_loop->ReleaseSoon(FROM_HERE, request);
}
private:
explicit DevicesRequest(const DescriptorsCallback& callback)
: response_message_loop_(base::MessageLoopProxy::current()),
callback_(callback),
descriptors_(new DeviceDescriptors()) {
}
friend class base::RefCountedThreadSafe<DevicesRequest>;
~DevicesRequest() {
response_message_loop_->PostTask(FROM_HERE,
base::Bind(callback_, descriptors_.release()));
}
typedef std::vector<std::string> Serials;
void ProcessSerials(scoped_refptr<DeviceProvider> provider,
const Serials& serials) {
for (Serials::const_iterator it = serials.begin(); it != serials.end();
++it) {
descriptors_->resize(descriptors_->size() + 1);
descriptors_->back().provider = provider;
descriptors_->back().serial = *it;
}
}
scoped_refptr<base::MessageLoopProxy> response_message_loop_;
DescriptorsCallback callback_;
scoped_ptr<DeviceDescriptors> descriptors_;
};
void ReleaseDeviceAndProvider(
AndroidDeviceManager::DeviceProvider* provider,
const std::string& serial) {
provider->ReleaseDevice(serial);
provider->Release();
}
} // namespace
AndroidDeviceManager::BrowserInfo::BrowserInfo()
: type(kTypeOther) {
}
AndroidDeviceManager::DeviceInfo::DeviceInfo() {
AndroidDeviceManager::DeviceInfo::DeviceInfo()
: model(kModelOffline), connected(false) {
}
AndroidDeviceManager::DeviceInfo::~DeviceInfo() {
}
AndroidDeviceManager::Device::Device(const std::string& serial,
bool is_connected)
: serial_(serial),
is_connected_(is_connected) {
AndroidDeviceManager::DeviceDescriptor::DeviceDescriptor() {
}
void AndroidDeviceManager::Device::HttpQuery(const std::string& socket_name,
const std::string& path,
const CommandCallback& callback) {
std::string request(base::StringPrintf(kHttpGetRequest, path.c_str()));
OpenSocket(socket_name,
base::Bind(&HttpRequest::CommandRequest, request, callback));
AndroidDeviceManager::DeviceDescriptor::~DeviceDescriptor() {
}
AndroidDeviceManager::Device::~Device() {
void AndroidDeviceManager::DeviceProvider::SendJsonRequest(
const std::string& serial,
const std::string& socket_name,
const std::string& request,
const CommandCallback& callback) {
OpenSocket(serial,
socket_name,
base::Bind(&HttpRequest::CommandRequest,
base::StringPrintf(kHttpGetRequest, request.c_str()),
callback));
}
void AndroidDeviceManager::DeviceProvider::HttpUpgrade(
const std::string& serial,
const std::string& socket_name,
const std::string& url,
const SocketCallback& callback) {
OpenSocket(
serial,
socket_name,
base::Bind(&HttpRequest::SocketRequest,
base::StringPrintf(kWebSocketUpgradeRequest, url.c_str()),
callback));
}
void AndroidDeviceManager::DeviceProvider::ReleaseDevice(
const std::string& serial) {
}
AndroidDeviceManager::DeviceProvider::DeviceProvider() {
......@@ -209,131 +322,181 @@ AndroidDeviceManager::DeviceProvider::DeviceProvider() {
AndroidDeviceManager::DeviceProvider::~DeviceProvider() {
}
// static
scoped_refptr<AndroidDeviceManager> AndroidDeviceManager::Create() {
return new AndroidDeviceManager();
void AndroidDeviceManager::Device::QueryDeviceInfo(
const DeviceInfoCallback& callback) {
device_message_loop_->PostTask(
FROM_HERE,
base::Bind(&DeviceProvider::QueryDeviceInfo,
provider_,
serial_,
base::Bind(&PostDeviceInfoCallback,
base::MessageLoopProxy::current(),
callback)));
}
void AndroidDeviceManager::QueryDevices(
const DeviceProviders& providers,
const QueryDevicesCallback& callback) {
DCHECK(CalledOnValidThread());
stopped_ = false;
Devices empty;
QueryNextProvider(callback, providers, empty, empty);
void AndroidDeviceManager::Device::OpenSocket(const std::string& socket_name,
const SocketCallback& callback) {
device_message_loop_->PostTask(
FROM_HERE,
base::Bind(&DeviceProvider::OpenSocket,
provider_,
serial_,
socket_name,
callback));
}
void AndroidDeviceManager::Stop() {
DCHECK(CalledOnValidThread());
stopped_ = true;
devices_.clear();
void AndroidDeviceManager::Device::SendJsonRequest(
const std::string& socket_name,
const std::string& request,
const CommandCallback& callback) {
device_message_loop_->PostTask(
FROM_HERE,
base::Bind(&DeviceProvider::SendJsonRequest,
provider_,
serial_,
socket_name,
request,
base::Bind(&PostCommandCallback,
base::MessageLoopProxy::current(),
callback)));
}
bool AndroidDeviceManager::IsConnected(const std::string& serial) {
DCHECK(CalledOnValidThread());
Device* device = FindDevice(serial);
return device && device->is_connected();
void AndroidDeviceManager::Device::HttpUpgrade(const std::string& socket_name,
const std::string& url,
const SocketCallback& callback) {
device_message_loop_->PostTask(
FROM_HERE,
base::Bind(&DeviceProvider::HttpUpgrade,
provider_,
serial_,
socket_name,
url,
base::Bind(&PostSocketCallback,
base::MessageLoopProxy::current(),
callback)));
}
void AndroidDeviceManager::QueryDeviceInfo(const std::string& serial,
const DeviceInfoCallback& callback) {
DCHECK(CalledOnValidThread());
Device* device = FindDevice(serial);
if (device)
device->QueryDeviceInfo(callback);
else
callback.Run(DeviceInfo());
AndroidDeviceManager::Device::Device(
scoped_refptr<base::MessageLoopProxy> device_message_loop,
scoped_refptr<DeviceProvider> provider,
const std::string& serial)
: device_message_loop_(device_message_loop),
provider_(provider),
serial_(serial),
weak_factory_(this) {
}
void AndroidDeviceManager::OpenSocket(
const std::string& serial,
const std::string& socket_name,
const SocketCallback& callback) {
DCHECK(CalledOnValidThread());
Device* device = FindDevice(serial);
if (device)
device->OpenSocket(socket_name, callback);
else
callback.Run(net::ERR_CONNECTION_FAILED, NULL);
AndroidDeviceManager::Device::~Device() {
provider_->AddRef();
DeviceProvider* raw_ptr = provider_.get();
provider_ = NULL;
device_message_loop_->PostTask(
FROM_HERE,
base::Bind(&ReleaseDeviceAndProvider,
base::Unretained(raw_ptr),
serial_));
}
void AndroidDeviceManager::HttpQuery(
const std::string& serial,
const std::string& socket_name,
const std::string& request,
const CommandCallback& callback) {
DCHECK(CalledOnValidThread());
Device* device = FindDevice(serial);
if (device)
device->HttpQuery(socket_name, request, callback);
else
callback.Run(net::ERR_CONNECTION_FAILED, std::string());
AndroidDeviceManager::HandlerThread*
AndroidDeviceManager::HandlerThread::instance_ = NULL;
// static
scoped_refptr<AndroidDeviceManager::HandlerThread>
AndroidDeviceManager::HandlerThread::GetInstance() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!instance_)
new HandlerThread();
return instance_;
}
void AndroidDeviceManager::HttpUpgrade(
const std::string& serial,
const std::string& socket_name,
const std::string& url,
const SocketCallback& callback) {
DCHECK(CalledOnValidThread());
Device* device = FindDevice(serial);
if (device) {
device->OpenSocket(
socket_name,
base::Bind(&HttpRequest::SocketRequest,
base::StringPrintf(kWebSocketUpgradeRequest, url.c_str()),
callback));
} else {
callback.Run(net::ERR_CONNECTION_FAILED, NULL);
AndroidDeviceManager::HandlerThread::HandlerThread() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
instance_ = this;
thread_ = new base::Thread(kDevToolsAdbBridgeThreadName);
base::Thread::Options options;
options.message_loop_type = base::MessageLoop::TYPE_IO;
if (!thread_->StartWithOptions(options)) {
delete thread_;
thread_ = NULL;
}
}
AndroidDeviceManager::AndroidDeviceManager()
: stopped_(false) {
scoped_refptr<base::MessageLoopProxy>
AndroidDeviceManager::HandlerThread::message_loop() {
return thread_ ? thread_->message_loop_proxy() : NULL;
}
AndroidDeviceManager::~AndroidDeviceManager() {
// static
void AndroidDeviceManager::HandlerThread::StopThread(
base::Thread* thread) {
thread->Stop();
}
void AndroidDeviceManager::QueryNextProvider(
const QueryDevicesCallback& callback,
const DeviceProviders& providers,
const Devices& total_devices,
const Devices& new_devices) {
DCHECK(CalledOnValidThread());
if (stopped_)
AndroidDeviceManager::HandlerThread::~HandlerThread() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
instance_ = NULL;
if (!thread_)
return;
// Shut down thread on FILE thread to join into IO.
content::BrowserThread::PostTask(
content::BrowserThread::FILE, FROM_HERE,
base::Bind(&HandlerThread::StopThread, thread_));
}
Devices more_devices(total_devices);
more_devices.insert(
more_devices.end(), new_devices.begin(), new_devices.end());
if (providers.empty()) {
std::vector<std::string> serials;
devices_.clear();
for (Devices::const_iterator it = more_devices.begin();
it != more_devices.end(); ++it) {
devices_[(*it)->serial()] = *it;
serials.push_back((*it)->serial());
}
callback.Run(serials);
return;
// static
scoped_refptr<AndroidDeviceManager> AndroidDeviceManager::Create() {
return new AndroidDeviceManager();
}
void AndroidDeviceManager::SetDeviceProviders(
const DeviceProviders& providers) {
for (DeviceProviders::iterator it = providers_.begin();
it != providers_.end(); ++it) {
(*it)->AddRef();
DeviceProvider* raw_ptr = it->get();
*it = NULL;
handler_thread_->message_loop()->ReleaseSoon(FROM_HERE, raw_ptr);
}
providers_ = providers;
}
void AndroidDeviceManager::QueryDevices(const DevicesCallback& callback) {
DevicesRequest::Start(handler_thread_->message_loop(),
providers_,
base::Bind(&AndroidDeviceManager::UpdateDevices,
this,
callback));
}
AndroidDeviceManager::AndroidDeviceManager()
: handler_thread_(HandlerThread::GetInstance()) {
}
scoped_refptr<DeviceProvider> current_provider = providers.back();
DeviceProviders less_providers = providers;
less_providers.pop_back();
current_provider->QueryDevices(
base::Bind(&AndroidDeviceManager::QueryNextProvider,
this, callback, less_providers, more_devices));
AndroidDeviceManager::~AndroidDeviceManager() {
SetDeviceProviders(DeviceProviders());
}
AndroidDeviceManager::Device*
AndroidDeviceManager::FindDevice(const std::string& serial) {
DCHECK(CalledOnValidThread());
DeviceMap::const_iterator it = devices_.find(serial);
if (it == devices_.end())
return NULL;
return (*it).second.get();
void AndroidDeviceManager::UpdateDevices(
const DevicesCallback& callback,
DeviceDescriptors* descriptors_raw) {
scoped_ptr<DeviceDescriptors> descriptors(descriptors_raw);
Devices response;
DeviceWeakMap new_devices;
for (DeviceDescriptors::const_iterator it = descriptors->begin();
it != descriptors->end();
++it) {
DeviceWeakMap::iterator found = devices_.find(it->serial);
scoped_refptr<Device> device;
if (found == devices_.end() || !found->second
|| found->second->provider_ != it->provider) {
device = new Device(handler_thread_->message_loop(),
it->provider, it->serial);
} else {
device = found->second.get();
}
response.push_back(device);
new_devices[it->serial] = device->weak_factory_.GetWeakPtr();
}
devices_.swap(new_devices);
callback.Run(response);
}
......@@ -23,6 +23,7 @@ class AndroidDeviceManager
public:
typedef base::Callback<void(int, const std::string&)> CommandCallback;
typedef base::Callback<void(int result, net::StreamSocket*)> SocketCallback;
typedef base::Callback<void(const std::vector<std::string>&)> SerialsCallback;
struct BrowserInfo {
BrowserInfo();
......@@ -43,117 +44,170 @@ class AndroidDeviceManager
~DeviceInfo();
std::string model;
bool connected;
gfx::Size screen_size;
std::vector<BrowserInfo> browser_info;
};
typedef base::Callback<void(const DeviceInfo&)> DeviceInfoCallback;
class Device : public base::RefCounted<Device>,
public base::NonThreadSafe {
class AndroidWebSocket : public base::RefCountedThreadSafe<AndroidWebSocket> {
public:
class Delegate {
public:
virtual void OnSocketOpened() = 0;
virtual void OnFrameRead(const std::string& message) = 0;
virtual void OnSocketClosed(bool closed_by_device) = 0;
protected:
virtual ~Delegate() {}
};
AndroidWebSocket() {}
virtual void Connect() = 0;
virtual void Disconnect() = 0;
virtual void SendFrame(const std::string& message) = 0;
virtual void ClearDelegate() = 0;
protected:
friend class AndroidDeviceManager;
virtual ~AndroidWebSocket() {}
private:
friend class base::RefCountedThreadSafe<AndroidWebSocket>;
DISALLOW_COPY_AND_ASSIGN(AndroidWebSocket);
};
class DeviceProvider;
class Device : public base::RefCountedThreadSafe<Device>,
public base::NonThreadSafe {
public:
typedef AndroidDeviceManager::DeviceInfoCallback DeviceInfoCallback;
typedef AndroidDeviceManager::CommandCallback CommandCallback;
typedef AndroidDeviceManager::SocketCallback SocketCallback;
typedef AndroidDeviceManager::DeviceInfoCallback DeviceInfoCallback;
Device(const std::string& serial, bool is_connected);
void QueryDeviceInfo(const DeviceInfoCallback& callback);
virtual void QueryDeviceInfo(const DeviceInfoCallback& callback) = 0;
void OpenSocket(const std::string& socket_name,
const SocketCallback& callback);
virtual void OpenSocket(const std::string& socket_name,
const SocketCallback& callback) = 0;
void SendJsonRequest(const std::string& socket_name,
const std::string& request,
const CommandCallback& callback);
void HttpUpgrade(const std::string& socket_name,
const std::string& url,
const SocketCallback& callback);
virtual void HttpQuery(const std::string& socket_name,
const std::string& request,
const CommandCallback& callback);
scoped_refptr<AndroidWebSocket> CreateWebSocket(
const std::string& socket_name,
const std::string& url,
AndroidWebSocket::Delegate* delegate);
std::string serial() { return serial_; }
bool is_connected() { return is_connected_; }
friend class base::RefCounted<Device>;
private:
friend class AndroidDeviceManager;
Device(scoped_refptr<base::MessageLoopProxy> device_message_loop,
scoped_refptr<DeviceProvider> provider,
const std::string& serial);
friend class base::RefCountedThreadSafe<Device>;
virtual ~Device();
private:
const std::string serial_;
const bool is_connected_;
scoped_refptr<base::MessageLoopProxy> device_message_loop_;
scoped_refptr<DeviceProvider> provider_;
std::string serial_;
base::WeakPtrFactory<Device> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(Device);
};
typedef std::vector<scoped_refptr<Device> > Devices;
typedef base::Callback<void(const Devices&)> DevicesCallback;
class DeviceProvider
: public base::RefCountedThreadSafe<
DeviceProvider,
content::BrowserThread::DeleteOnUIThread> {
protected:
friend class AndroidDeviceManager;
class DeviceProvider : public base::RefCountedThreadSafe<DeviceProvider> {
public:
typedef AndroidDeviceManager::SerialsCallback SerialsCallback;
typedef AndroidDeviceManager::DeviceInfoCallback DeviceInfoCallback;
typedef AndroidDeviceManager::SocketCallback SocketCallback;
typedef AndroidDeviceManager::CommandCallback CommandCallback;
typedef base::Callback<void(const Devices&)> QueryDevicesCallback;
virtual void QueryDevices(const SerialsCallback& callback) = 0;
virtual void QueryDevices(const QueryDevicesCallback& callback) = 0;
virtual void QueryDeviceInfo(const std::string& serial,
const DeviceInfoCallback& callback) = 0;
protected:
friend struct
content::BrowserThread::DeleteOnThread<content::BrowserThread::UI>;
friend class base::DeleteHelper<DeviceProvider>;
virtual void OpenSocket(const std::string& serial,
const std::string& socket_name,
const SocketCallback& callback) = 0;
virtual void SendJsonRequest(const std::string& serial,
const std::string& socket_name,
const std::string& request,
const CommandCallback& callback);
virtual void HttpUpgrade(const std::string& serial,
const std::string& socket_name,
const std::string& url,
const SocketCallback& callback);
virtual void ReleaseDevice(const std::string& serial);
protected:
friend class base::RefCountedThreadSafe<DeviceProvider>;
DeviceProvider();
virtual ~DeviceProvider();
};
public:
static scoped_refptr<AndroidDeviceManager> Create();
typedef std::vector<scoped_refptr<DeviceProvider> > DeviceProviders;
typedef base::Callback<void (const std::vector<std::string>&)>
QueryDevicesCallback;
void QueryDevices(const DeviceProviders& providers,
const QueryDevicesCallback& callback);
void Stop();
static scoped_refptr<AndroidDeviceManager> Create();
bool IsConnected(const std::string& serial);
void SetDeviceProviders(const DeviceProviders& providers);
void QueryDeviceInfo(const std::string& serial,
const DeviceInfoCallback& callback);
void QueryDevices(const DevicesCallback& callback);
void OpenSocket(const std::string& serial,
const std::string& socket_name,
const SocketCallback& callback);
struct DeviceDescriptor {
DeviceDescriptor();
~DeviceDescriptor();
void HttpQuery(const std::string& serial,
const std::string& socket_name,
const std::string& request,
const CommandCallback& callback);
scoped_refptr<DeviceProvider> provider;
std::string serial;
};
void HttpUpgrade(const std::string& serial,
const std::string& socket_name,
const std::string& url,
const SocketCallback& callback);
typedef std::vector<DeviceDescriptor> DeviceDescriptors;
private:
AndroidDeviceManager();
class HandlerThread : public base::RefCountedThreadSafe<HandlerThread> {
public:
static scoped_refptr<HandlerThread> GetInstance();
scoped_refptr<base::MessageLoopProxy> message_loop();
friend class base::RefCountedThreadSafe<AndroidDeviceManager>;
private:
friend class base::RefCountedThreadSafe<HandlerThread>;
static HandlerThread* instance_;
static void StopThread(base::Thread* thread);
virtual ~AndroidDeviceManager();
HandlerThread();
virtual ~HandlerThread();
base::Thread* thread_;
};
void QueryNextProvider(
const QueryDevicesCallback& callback,
const DeviceProviders& providers,
const Devices& total_devices,
const Devices& new_devices);
friend class base::RefCountedThreadSafe<AndroidDeviceManager>;
AndroidDeviceManager();
virtual ~AndroidDeviceManager();
Device* FindDevice(const std::string& serial);
void UpdateDevices(const DevicesCallback& callback,
DeviceDescriptors* descriptors);
typedef std::map<std::string, scoped_refptr<Device> > DeviceMap;
DeviceMap devices_;
typedef std::map<std::string, base::WeakPtr<Device> > DeviceWeakMap;
bool stopped_;
scoped_refptr<HandlerThread> handler_thread_;
DeviceProviders providers_;
DeviceWeakMap devices_;
};
#endif // CHROME_BROWSER_DEVTOOLS_DEVICE_ANDROID_DEVICE_MANAGER_H_
......@@ -4,7 +4,7 @@
#include "base/message_loop/message_loop.h"
#include "base/rand_util.h"
#include "chrome/browser/devtools/device/devtools_android_bridge.h"
#include "chrome/browser/devtools/device/android_device_manager.h"
#include "content/public/browser/browser_thread.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
......@@ -18,15 +18,14 @@ namespace {
const int kBufferSize = 16 * 1024;
class WebSocketImpl : public DevToolsAndroidBridge::AndroidWebSocket {
class WebSocketImpl : public AndroidDeviceManager::AndroidWebSocket {
public:
WebSocketImpl(scoped_refptr<DevToolsAndroidBridge> android_bridge,
AndroidDeviceManager* device_manager,
base::MessageLoop* device_message_loop,
const std::string& serial,
const std::string& socket_name,
const std::string& url,
Delegate* delegate);
typedef AndroidDeviceManager::Device Device;
WebSocketImpl(scoped_refptr<base::MessageLoopProxy> device_message_loop,
scoped_refptr<Device> device,
const std::string& socket_name,
const std::string& url,
Delegate* delegate);
virtual void Connect() OVERRIDE;
virtual void Disconnect() OVERRIDE;
......@@ -38,8 +37,7 @@ class WebSocketImpl : public DevToolsAndroidBridge::AndroidWebSocket {
virtual ~WebSocketImpl();
void ConnectOnHandlerThread();
void ConnectedOnHandlerThread(int result, net::StreamSocket* socket);
void Connected(int result, net::StreamSocket* socket);
void StartListeningOnHandlerThread();
void OnBytesRead(scoped_refptr<net::IOBuffer> response_buffer, int result);
void SendFrameOnHandlerThread(const std::string& message);
......@@ -50,10 +48,8 @@ class WebSocketImpl : public DevToolsAndroidBridge::AndroidWebSocket {
void OnFrameRead(const std::string& message);
void OnSocketClosed(bool closed_by_device);
scoped_refptr<DevToolsAndroidBridge> android_bridge_;
AndroidDeviceManager* device_manager_;
base::MessageLoop* device_message_loop_;
std::string serial_;
scoped_refptr<base::MessageLoopProxy> device_message_loop_;
scoped_refptr<Device> device_;
std::string socket_name_;
std::string url_;
scoped_ptr<net::StreamSocket> socket_;
......@@ -63,17 +59,13 @@ class WebSocketImpl : public DevToolsAndroidBridge::AndroidWebSocket {
};
WebSocketImpl::WebSocketImpl(
scoped_refptr<DevToolsAndroidBridge> android_bridge,
AndroidDeviceManager* device_manager,
base::MessageLoop* device_message_loop,
const std::string& serial,
scoped_refptr<base::MessageLoopProxy> device_message_loop,
scoped_refptr<Device> device,
const std::string& socket_name,
const std::string& url,
Delegate* delegate)
: android_bridge_(android_bridge),
device_manager_(device_manager),
device_message_loop_(device_message_loop),
serial_(serial),
: device_message_loop_(device_message_loop),
device_(device),
socket_name_(socket_name),
url_(url),
delegate_(delegate) {
......@@ -81,11 +73,12 @@ WebSocketImpl::WebSocketImpl(
void WebSocketImpl::Connect() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
device_message_loop_->PostTask(
FROM_HERE, base::Bind(&WebSocketImpl::ConnectOnHandlerThread, this));
device_->HttpUpgrade(
socket_name_, url_, base::Bind(&WebSocketImpl::Connected, this));
}
void WebSocketImpl::Disconnect() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
device_message_loop_->PostTask(
FROM_HERE,
base::Bind(&WebSocketImpl::DisconnectOnHandlerThread, this, false));
......@@ -103,6 +96,7 @@ void WebSocketImpl::ClearDelegate() {
}
void WebSocketImpl::SendFrameOnHandlerThread(const std::string& message) {
DCHECK_EQ(device_message_loop_, base::MessageLoopProxy::current());
int mask = base::RandInt(0, 0x7FFFFFFF);
std::string encoded_frame = WebSocket::EncodeFrameHybi17(message, mask);
request_buffer_ += encoded_frame;
......@@ -110,30 +104,25 @@ void WebSocketImpl::SendFrameOnHandlerThread(const std::string& message) {
SendPendingRequests(0);
}
WebSocketImpl::~WebSocketImpl() {}
void WebSocketImpl::ConnectOnHandlerThread() {
device_manager_->HttpUpgrade(
serial_,
socket_name_,
url_,
base::Bind(&WebSocketImpl::ConnectedOnHandlerThread, this));
WebSocketImpl::~WebSocketImpl() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}
void WebSocketImpl::ConnectedOnHandlerThread(
int result, net::StreamSocket* socket) {
void WebSocketImpl::Connected(int result, net::StreamSocket* socket) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (result != net::OK || socket == NULL) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::Bind(&WebSocketImpl::OnSocketClosed, this, true));
OnSocketClosed(true);
return;
}
socket_.reset(socket);
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::Bind(&WebSocketImpl::OnSocketOpened, this));
StartListeningOnHandlerThread();
device_message_loop_->PostTask(
FROM_HERE,
base::Bind(&WebSocketImpl::StartListeningOnHandlerThread, this));
OnSocketOpened();
}
void WebSocketImpl::StartListeningOnHandlerThread() {
DCHECK_EQ(device_message_loop_, base::MessageLoopProxy::current());
scoped_refptr<net::IOBuffer> response_buffer =
new net::IOBuffer(kBufferSize);
int result = socket_->Read(
......@@ -146,6 +135,7 @@ void WebSocketImpl::StartListeningOnHandlerThread() {
void WebSocketImpl::OnBytesRead(
scoped_refptr<net::IOBuffer> response_buffer, int result) {
DCHECK_EQ(device_message_loop_, base::MessageLoopProxy::current());
if (!socket_)
return;
......@@ -185,6 +175,7 @@ void WebSocketImpl::OnBytesRead(
}
void WebSocketImpl::SendPendingRequests(int result) {
DCHECK_EQ(device_message_loop_, base::MessageLoopProxy::current());
if (!socket_)
return;
if (result < 0) {
......@@ -205,6 +196,7 @@ void WebSocketImpl::SendPendingRequests(int result) {
}
void WebSocketImpl::DisconnectOnHandlerThread(bool closed_by_device) {
DCHECK_EQ(device_message_loop_, base::MessageLoopProxy::current());
if (!socket_)
return;
// Wipe out socket_ first since Disconnect can re-enter this method.
......@@ -231,13 +223,10 @@ void WebSocketImpl::OnSocketClosed(bool closed_by_device) {
} // namespace
scoped_refptr<DevToolsAndroidBridge::AndroidWebSocket>
DevToolsAndroidBridge::RemoteBrowser::CreateWebSocket(
scoped_refptr<AndroidDeviceManager::AndroidWebSocket>
AndroidDeviceManager::Device::CreateWebSocket(
const std::string& socket,
const std::string& url,
DevToolsAndroidBridge::AndroidWebSocket::Delegate* delegate) {
return new WebSocketImpl(
android_bridge_,
android_bridge_->device_manager(),
android_bridge_->device_message_loop(),
serial_, socket_, url, delegate);
AndroidDeviceManager::AndroidWebSocket::Delegate* delegate) {
return new WebSocketImpl(device_message_loop_, this, socket, url, delegate);
}
......@@ -41,8 +41,6 @@ using content::BrowserThread;
namespace {
const char kModelOffline[] = "Offline";
const char kPageListRequest[] = "/json";
const char kVersionRequest[] = "/json/version";
const char kClosePageRequest[] = "/json/close/%s";
......@@ -65,14 +63,14 @@ class DiscoveryRequest : public base::RefCountedThreadSafe<
DiscoveryRequest,
BrowserThread::DeleteOnUIThread> {
public:
typedef base::Callback<void(DevToolsAndroidBridge::RemoteDevices*)> Callback;
typedef base::Callback<void(scoped_ptr<DevToolsAndroidBridge::RemoteDevices>)>
DiscoveryCallback;
typedef AndroidDeviceManager::Device Device;
typedef AndroidDeviceManager::Devices Devices;
DiscoveryRequest(
scoped_refptr<DevToolsAndroidBridge> android_bridge,
AndroidDeviceManager* device_manager,
base::MessageLoop* device_message_loop,
const AndroidDeviceManager::DeviceProviders& device_providers,
const Callback& callback);
const DiscoveryCallback& callback);
private:
friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>;
......@@ -80,14 +78,14 @@ class DiscoveryRequest : public base::RefCountedThreadSafe<
virtual ~DiscoveryRequest();
void ReceivedSerials(const std::vector<std::string>& serials);
void ProcessSerials();
void ReceivedDevices(const Devices& devices);
void ProcessDevices();
void ReceivedDeviceInfo(const AndroidDeviceManager::DeviceInfo& device_info);
void ProcessSockets();
void ReceivedVersion(int result, const std::string& response);
void ReceivedPages(int result, const std::string& response);
std::string current_serial() const { return serials_.back(); }
scoped_refptr<Device> current_device() { return devices_.back(); }
scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> current_browser() const {
return browsers_.back();
......@@ -98,84 +96,59 @@ class DiscoveryRequest : public base::RefCountedThreadSafe<
void Respond();
scoped_refptr<DevToolsAndroidBridge> android_bridge_;
AndroidDeviceManager* device_manager_;
base::MessageLoop* device_message_loop_;
Callback callback_;
std::vector<std::string> serials_;
DiscoveryCallback callback_;
Devices devices_;
DevToolsAndroidBridge::RemoteBrowsers browsers_;
scoped_ptr<DevToolsAndroidBridge::RemoteDevices> remote_devices_;
};
DiscoveryRequest::DiscoveryRequest(
scoped_refptr<DevToolsAndroidBridge> android_bridge,
AndroidDeviceManager* device_manager,
base::MessageLoop* device_message_loop,
const AndroidDeviceManager::DeviceProviders& device_providers,
const Callback& callback)
: android_bridge_(android_bridge),
device_manager_(device_manager),
device_message_loop_(device_message_loop),
callback_(callback) {
const DiscoveryCallback& callback)
: callback_(callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
remote_devices_.reset(new DevToolsAndroidBridge::RemoteDevices());
device_message_loop_->PostTask(
FROM_HERE, base::Bind(
&AndroidDeviceManager::QueryDevices,
device_manager_,
device_providers,
base::Bind(&DiscoveryRequest::ReceivedSerials, this)));
device_manager->QueryDevices(
base::Bind(&DiscoveryRequest::ReceivedDevices, this));
}
DiscoveryRequest::~DiscoveryRequest() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}
void DiscoveryRequest::ReceivedSerials(
const std::vector<std::string>& serials) {
DCHECK_EQ(device_message_loop_, base::MessageLoop::current());
serials_ = serials;
ProcessSerials();
void DiscoveryRequest::ReceivedDevices(const Devices& devices) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
devices_ = devices;
ProcessDevices();
}
void DiscoveryRequest::ProcessSerials() {
DCHECK_EQ(device_message_loop_, base::MessageLoop::current());
if (serials_.size() == 0) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&DiscoveryRequest::Respond, this));
void DiscoveryRequest::ProcessDevices() {
if (devices_.size() == 0) {
Respond();
return;
}
if (device_manager_->IsConnected(current_serial())) {
device_manager_->QueryDeviceInfo(current_serial(),
base::Bind(&DiscoveryRequest::ReceivedDeviceInfo, this));
} else {
AndroidDeviceManager::DeviceInfo offline_info;
offline_info.model = kModelOffline;
remote_devices_->push_back(new DevToolsAndroidBridge::RemoteDevice(
android_bridge_, current_serial(), offline_info, false));
NextDevice();
}
current_device()->QueryDeviceInfo(
base::Bind(&DiscoveryRequest::ReceivedDeviceInfo, this));
}
void DiscoveryRequest::ReceivedDeviceInfo(
const AndroidDeviceManager::DeviceInfo& device_info) {
remote_devices_->push_back(new DevToolsAndroidBridge::RemoteDevice(
android_bridge_, current_serial(), device_info, true));
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
remote_devices_->push_back(
new DevToolsAndroidBridge::RemoteDevice(current_device(), device_info));
browsers_ = remote_devices_->back()->browsers();
ProcessSockets();
}
void DiscoveryRequest::ProcessSockets() {
DCHECK_EQ(device_message_loop_, base::MessageLoop::current());
if (browsers_.size() == 0) {
NextDevice();
return;
}
device_manager_->HttpQuery(
current_serial(),
current_device()->SendJsonRequest(
current_browser()->socket(),
kVersionRequest,
base::Bind(&DiscoveryRequest::ReceivedVersion, this));
......@@ -183,7 +156,7 @@ void DiscoveryRequest::ProcessSockets() {
void DiscoveryRequest::ReceivedVersion(int result,
const std::string& response) {
DCHECK_EQ(device_message_loop_, base::MessageLoop::current());
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (result < 0) {
NextBrowser();
return;
......@@ -210,8 +183,7 @@ void DiscoveryRequest::ReceivedVersion(int result,
}
}
device_manager_->HttpQuery(
current_serial(),
current_device()->SendJsonRequest(
current_browser()->socket(),
kPageListRequest,
base::Bind(&DiscoveryRequest::ReceivedPages, this));
......@@ -219,7 +191,7 @@ void DiscoveryRequest::ReceivedVersion(int result,
void DiscoveryRequest::ReceivedPages(int result,
const std::string& response) {
DCHECK_EQ(device_message_loop_, base::MessageLoop::current());
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (result >= 0) {
scoped_ptr<base::Value> value(base::JSONReader::Read(response));
base::ListValue* list_value;
......@@ -235,12 +207,12 @@ void DiscoveryRequest::NextBrowser() {
}
void DiscoveryRequest::NextDevice() {
serials_.pop_back();
ProcessSerials();
devices_.pop_back();
ProcessDevices();
}
void DiscoveryRequest::Respond() {
callback_.Run(remote_devices_.release());
callback_.Run(remote_devices_.Pass());
}
// ProtocolCommand ------------------------------------------------------------
......@@ -588,11 +560,9 @@ void RemotePageTarget::Navigate(const std::string& url,
// DevToolsAndroidBridge::RemoteBrowser ---------------------------------------
DevToolsAndroidBridge::RemoteBrowser::RemoteBrowser(
scoped_refptr<DevToolsAndroidBridge> android_bridge,
const std::string& serial,
scoped_refptr<Device> device,
const AndroidDeviceManager::BrowserInfo& browser_info)
: android_bridge_(android_bridge),
serial_(serial),
: device_(device),
socket_(browser_info.socket_name),
display_name_(browser_info.display_name),
type_(browser_info.type),
......@@ -642,7 +612,7 @@ void DevToolsAndroidBridge::RemoteBrowser::SetPageDescriptors(
}
static void RespondOnUIThread(
const DevToolsAndroidBridge::RemoteBrowser::JsonRequestCallback& callback,
const DevToolsAndroidBridge::JsonRequestCallback& callback,
int result,
const std::string& response) {
if (callback.is_null())
......@@ -653,12 +623,7 @@ static void RespondOnUIThread(
void DevToolsAndroidBridge::RemoteBrowser::SendJsonRequest(
const std::string& request, const JsonRequestCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
android_bridge_->device_message_loop()->PostTask(
FROM_HERE,
base::Bind(&AndroidDeviceManager::HttpQuery,
android_bridge_->device_manager(), serial_, socket_, request,
base::Bind(&RespondOnUIThread, callback)));
device_->SendJsonRequest(socket_, request, callback);
}
void DevToolsAndroidBridge::RemoteBrowser::SendProtocolCommand(
......@@ -684,7 +649,14 @@ void DevToolsAndroidBridge::RemoteBrowser::Open(
scoped_refptr<content::DevToolsAgentHost>
DevToolsAndroidBridge::RemoteBrowser::GetAgentHost() {
return AgentHostDelegate::GetOrCreateAgentHost(
"adb:" + serial_ + ":" + socket_, this, kBrowserTargetSocket);
"adb:" + device_->serial() + ":" + socket_, this, kBrowserTargetSocket);
}
scoped_refptr<DevToolsAndroidBridge::AndroidWebSocket>
DevToolsAndroidBridge::RemoteBrowser::CreateWebSocket(
const std::string& url,
DevToolsAndroidBridge::AndroidWebSocket::Delegate* delegate) {
return device_->CreateWebSocket(socket_, url, delegate);
}
void DevToolsAndroidBridge::RemoteBrowser::RespondToOpenOnUIThread(
......@@ -764,113 +736,50 @@ void DevToolsAndroidBridge::RemoteBrowser::NavigatePageOnUIThread(
DevToolsAndroidBridge::RemoteBrowser::~RemoteBrowser() {
}
// DevToolsAndroidBridge::RemoteDevice ----------------------------------------
DevToolsAndroidBridge::RemoteDevice::RemoteDevice(
scoped_refptr<DevToolsAndroidBridge> android_bridge,
const std::string& serial,
const AndroidDeviceManager::DeviceInfo& device_info,
bool connected)
: android_bridge_(android_bridge),
serial_(serial),
scoped_refptr<AndroidDeviceManager::Device> device,
const AndroidDeviceManager::DeviceInfo& device_info)
: device_(device),
model_(device_info.model),
connected_(connected),
connected_(device_info.connected),
screen_size_(device_info.screen_size) {
for (std::vector<AndroidDeviceManager::BrowserInfo>::const_iterator it =
device_info.browser_info.begin();
it != device_info.browser_info.end();
++it) {
browsers_.push_back(new DevToolsAndroidBridge::RemoteBrowser(
android_bridge_, serial_, *it));
browsers_.push_back(new DevToolsAndroidBridge::RemoteBrowser(device, *it));
}
}
void DevToolsAndroidBridge::RemoteDevice::OpenSocket(
const std::string& socket_name,
const AndroidDeviceManager::SocketCallback& callback) {
android_bridge_->device_message_loop()->PostTask(FROM_HERE,
base::Bind(&AndroidDeviceManager::OpenSocket,
android_bridge_->device_manager(),
serial_,
socket_name,
callback));
device_->OpenSocket(socket_name, callback);
}
DevToolsAndroidBridge::RemoteDevice::~RemoteDevice() {
}
// DevToolsAndroidBridge::HandlerThread ---------------------------------
const char kDevToolsAdbBridgeThreadName[] = "Chrome_DevToolsADBThread";
DevToolsAndroidBridge::HandlerThread*
DevToolsAndroidBridge::HandlerThread::instance_ = NULL;
// static
scoped_refptr<DevToolsAndroidBridge::HandlerThread>
DevToolsAndroidBridge::HandlerThread::GetInstance() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!instance_)
new HandlerThread();
return instance_;
}
DevToolsAndroidBridge::HandlerThread::HandlerThread() {
instance_ = this;
thread_ = new base::Thread(kDevToolsAdbBridgeThreadName);
base::Thread::Options options;
options.message_loop_type = base::MessageLoop::TYPE_IO;
if (!thread_->StartWithOptions(options)) {
delete thread_;
thread_ = NULL;
}
}
base::MessageLoop* DevToolsAndroidBridge::HandlerThread::message_loop() {
return thread_ ? thread_->message_loop() : NULL;
}
// static
void DevToolsAndroidBridge::HandlerThread::StopThread(
base::Thread* thread) {
thread->Stop();
}
DevToolsAndroidBridge::HandlerThread::~HandlerThread() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
instance_ = NULL;
if (!thread_)
return;
// Shut down thread on FILE thread to join into IO.
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
base::Bind(&HandlerThread::StopThread, thread_));
}
// DevToolsAndroidBridge ------------------------------------------------------
DevToolsAndroidBridge::DevToolsAndroidBridge(Profile* profile)
: profile_(profile),
handler_thread_(HandlerThread::GetInstance()) {
device_manager_(AndroidDeviceManager::Create()) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
pref_change_registrar_.Init(profile_->GetPrefs());
pref_change_registrar_.Add(prefs::kDevToolsDiscoverUsbDevicesEnabled,
base::Bind(&DevToolsAndroidBridge::CreateDeviceProviders,
base::Unretained(this)));
CreateDeviceProviders();
base::PostTaskAndReplyWithResult(
device_message_loop()->message_loop_proxy(),
FROM_HERE,
base::Bind(&AndroidDeviceManager::Create),
base::Bind(&DevToolsAndroidBridge::CreatedDeviceManager, this));
}
void DevToolsAndroidBridge::AddDeviceListListener(
DeviceListListener* listener) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
device_list_listeners_.push_back(listener);
if (device_list_listeners_.size() == 1 && device_manager_)
if (device_list_listeners_.size() == 1)
RequestDeviceList();
}
......@@ -881,16 +790,14 @@ void DevToolsAndroidBridge::RemoveDeviceListListener(
device_list_listeners_.begin(), device_list_listeners_.end(), listener);
DCHECK(it != device_list_listeners_.end());
device_list_listeners_.erase(it);
if (device_list_listeners_.empty() && device_manager_) {
device_message_loop()->PostTask(FROM_HERE,
base::Bind(&AndroidDeviceManager::Stop, device_manager_));
}
if (device_list_listeners_.empty())
devices_.clear();
}
void DevToolsAndroidBridge::AddDeviceCountListener(
DeviceCountListener* listener) {
device_count_listeners_.push_back(listener);
if (device_count_listeners_.size() == 1 && device_manager_)
if (device_count_listeners_.size() == 1)
RequestDeviceCount();
}
......@@ -913,47 +820,28 @@ DevToolsAndroidBridge::~DevToolsAndroidBridge() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(device_list_listeners_.empty());
DCHECK(device_count_listeners_.empty());
if (device_manager_) {
AndroidDeviceManager* raw_ptr = device_manager_.get();
device_manager_->AddRef();
device_manager_ = NULL;
device_message_loop()->ReleaseSoon(FROM_HERE, raw_ptr);
}
}
void DevToolsAndroidBridge::RequestDeviceList() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(device_manager_);
if (device_list_listeners_.empty())
return;
new DiscoveryRequest(
this,
device_manager(),
device_message_loop(),
device_providers_,
device_manager_.get(),
base::Bind(&DevToolsAndroidBridge::ReceivedDeviceList, this));
}
void DevToolsAndroidBridge::CreatedDeviceManager(
scoped_refptr<AndroidDeviceManager> device_manager) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
device_manager_ = device_manager;
if (!device_list_listeners_.empty())
RequestDeviceList();
if (!device_count_listeners_.empty())
RequestDeviceCount();
}
void DevToolsAndroidBridge::ReceivedDeviceList(RemoteDevices* devices_ptr) {
void DevToolsAndroidBridge::ReceivedDeviceList(
scoped_ptr<RemoteDevices> devices) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
scoped_ptr<RemoteDevices> devices(devices_ptr);
if (device_list_listeners_.empty())
return;
devices_ = *devices;
DeviceListListeners copy(device_list_listeners_);
for (DeviceListListeners::iterator it = copy.begin(); it != copy.end(); ++it)
(*it)->DeviceListChanged(*devices.get());
......@@ -967,7 +855,6 @@ void DevToolsAndroidBridge::ReceivedDeviceList(RemoteDevices* devices_ptr) {
void DevToolsAndroidBridge::RequestDeviceCount() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(device_manager_);
if (device_count_listeners_.empty())
return;
......@@ -994,15 +881,15 @@ void DevToolsAndroidBridge::ReceivedDeviceCount(int count) {
}
void DevToolsAndroidBridge::CreateDeviceProviders() {
device_providers_.clear();
AndroidDeviceManager::DeviceProviders device_providers;
#if defined(DEBUG_DEVTOOLS)
BrowserListTabContentsProvider::EnableTethering();
// We cannot rely on command line switch here as we might want to connect
// to another instance of Chrome. Using hard-coded port number instead.
const int kDefaultDebuggingPort = 9222;
device_providers_.push_back(new SelfAsDeviceProvider(kDefaultDebuggingPort));
device_providers.push_back(new SelfAsDeviceProvider(kDefaultDebuggingPort));
#endif
device_providers_.push_back(new AdbDeviceProvider());
device_providers.push_back(new AdbDeviceProvider());
PrefService* service = profile_->GetPrefs();
const PrefService::Preference* pref =
......@@ -1011,6 +898,7 @@ void DevToolsAndroidBridge::CreateDeviceProviders() {
bool enabled;
if (pref_value->GetAsBoolean(&enabled) && enabled) {
device_providers_.push_back(new UsbDeviceProvider(profile_));
device_providers.push_back(new UsbDeviceProvider(profile_));
}
device_manager_->SetDeviceProviders(device_providers);
}
......@@ -72,34 +72,6 @@ class DevToolsAndroidBridge
DISALLOW_COPY_AND_ASSIGN(Factory);
};
class AndroidWebSocket : public base::RefCountedThreadSafe<AndroidWebSocket> {
public:
class Delegate {
public:
virtual void OnSocketOpened() = 0;
virtual void OnFrameRead(const std::string& message) = 0;
virtual void OnSocketClosed(bool closed_by_device) = 0;
protected:
virtual ~Delegate() {}
};
AndroidWebSocket() {}
virtual void Connect() = 0;
virtual void Disconnect() = 0;
virtual void SendFrame(const std::string& message) = 0;
virtual void ClearDelegate() = 0;
protected:
virtual ~AndroidWebSocket() {}
private:
friend class base::RefCountedThreadSafe<AndroidWebSocket>;
DISALLOW_COPY_AND_ASSIGN(AndroidWebSocket);
};
class RemotePage {
public:
virtual ~RemotePage() {}
......@@ -108,15 +80,16 @@ class DevToolsAndroidBridge
};
typedef base::Callback<void(RemotePage*)> RemotePageCallback;
typedef base::Callback<void(int, const std::string&)> JsonRequestCallback;
typedef AndroidDeviceManager::Device Device;
typedef AndroidDeviceManager::AndroidWebSocket AndroidWebSocket;
class RemoteBrowser : public base::RefCounted<RemoteBrowser> {
public:
RemoteBrowser(
scoped_refptr<DevToolsAndroidBridge> android_bridge,
const std::string& serial,
const AndroidDeviceManager::BrowserInfo& browser_info);
RemoteBrowser(scoped_refptr<Device> device,
const AndroidDeviceManager::BrowserInfo& browser_info);
std::string serial() { return serial_; }
std::string serial() { return device_->serial(); }
std::string socket() { return socket_; }
std::string display_name() { return display_name_; }
......@@ -134,9 +107,9 @@ class DevToolsAndroidBridge
std::vector<RemotePage*> CreatePages();
void SetPageDescriptors(const base::ListValue&);
typedef base::Callback<void(int, const std::string&)> JsonRequestCallback;
void SendJsonRequest(const std::string& request,
const JsonRequestCallback& callback);
void SendProtocolCommand(const std::string& debug_url,
const std::string& method,
base::DictionaryValue* params,
......@@ -172,8 +145,7 @@ class DevToolsAndroidBridge
int result,
const std::string& response);
scoped_refptr<DevToolsAndroidBridge> android_bridge_;
const std::string serial_;
scoped_refptr<Device> device_;
const std::string socket_;
std::string display_name_;
const AndroidDeviceManager::BrowserInfo::Type type_;
......@@ -187,12 +159,10 @@ class DevToolsAndroidBridge
class RemoteDevice : public base::RefCounted<RemoteDevice> {
public:
RemoteDevice(scoped_refptr<DevToolsAndroidBridge> android_bridge,
const std::string& serial,
const AndroidDeviceManager::DeviceInfo& device_info,
bool connected);
RemoteDevice(scoped_refptr<Device> device,
const AndroidDeviceManager::DeviceInfo& device_info);
std::string serial() { return serial_; }
std::string serial() { return device_->serial(); }
std::string model() { return model_; }
bool is_connected() { return connected_; }
RemoteBrowsers& browsers() { return browsers_; }
......@@ -205,8 +175,7 @@ class DevToolsAndroidBridge
friend class base::RefCounted<RemoteDevice>;
virtual ~RemoteDevice();
scoped_refptr<DevToolsAndroidBridge> android_bridge_;
std::string serial_;
scoped_refptr<Device> device_;
std::string model_;
bool connected_;
RemoteBrowsers browsers_;
......@@ -240,7 +209,7 @@ class DevToolsAndroidBridge
void set_device_providers_for_test(
const AndroidDeviceManager::DeviceProviders& device_providers) {
device_providers_ = device_providers;
device_manager_->SetDeviceProviders(device_providers);
}
static bool HasDevToolsWindow(const std::string& agent_id);
......@@ -250,43 +219,18 @@ class DevToolsAndroidBridge
content::BrowserThread::UI>;
friend class base::DeleteHelper<DevToolsAndroidBridge>;
class HandlerThread : public base::RefCountedThreadSafe<HandlerThread> {
public:
static scoped_refptr<HandlerThread> GetInstance();
base::MessageLoop* message_loop();
private:
friend class base::RefCountedThreadSafe<HandlerThread>;
static HandlerThread* instance_;
static void StopThread(base::Thread* thread);
HandlerThread();
virtual ~HandlerThread();
base::Thread* thread_;
};
virtual ~DevToolsAndroidBridge();
base::MessageLoop* device_message_loop() {
return handler_thread_->message_loop();
}
AndroidDeviceManager* device_manager() {
return device_manager_.get();
}
void CreatedDeviceManager(scoped_refptr<AndroidDeviceManager> device_manager);
void RequestDeviceList();
void ReceivedDeviceList(RemoteDevices* devices);
void ReceivedDeviceList(scoped_ptr<RemoteDevices> devices);
void RequestDeviceCount();
void ReceivedDeviceCount(int count);
void CreateDeviceProviders();
Profile* profile_;
scoped_refptr<HandlerThread> handler_thread_;
scoped_refptr<AndroidDeviceManager> device_manager_;
RemoteDevices devices_;
typedef std::vector<DeviceListListener*> DeviceListListeners;
DeviceListListeners device_list_listeners_;
......@@ -294,7 +238,6 @@ class DevToolsAndroidBridge
typedef std::vector<DeviceCountListener*> DeviceCountListeners;
DeviceCountListeners device_count_listeners_;
AndroidDeviceManager::DeviceProviders device_providers_;
PrefChangeRegistrar pref_change_registrar_;
DISALLOW_COPY_AND_ASSIGN(DevToolsAndroidBridge);
};
......
......@@ -13,29 +13,31 @@ namespace {
const char kDeviceModel[] = "Local Chrome";
const char kBrowserName[] = "Chrome";
const char kLocalhost[] = "127.0.0.1";
const char kSerial[] = "local";
class SelfAsDevice : public AndroidDeviceManager::Device {
public:
explicit SelfAsDevice(int port);
virtual void QueryDeviceInfo(const DeviceInfoCallback& callback) OVERRIDE;
static void RunSocketCallback(
const AndroidDeviceManager::SocketCallback& callback,
net::StreamSocket* socket,
int result) {
callback.Run(result, socket);
}
virtual void OpenSocket(const std::string& socket_name,
const SocketCallback& callback) OVERRIDE;
private:
virtual ~SelfAsDevice() {}
} // namespace
int port_;
};
SelfAsDeviceProvider::SelfAsDeviceProvider(int port) : port_(port) {
}
SelfAsDevice::SelfAsDevice(int port)
: Device("local", true),
port_(port)
{}
void SelfAsDeviceProvider::QueryDevices(const SerialsCallback& callback) {
std::vector<std::string> result;
result.push_back(kSerial);
callback.Run(result);
}
void SelfAsDevice::QueryDeviceInfo(const DeviceInfoCallback& callback) {
void SelfAsDeviceProvider::QueryDeviceInfo(const std::string& serial,
const DeviceInfoCallback& callback) {
AndroidDeviceManager::DeviceInfo device_info;
device_info.model = kDeviceModel;
device_info.connected = true;
AndroidDeviceManager::BrowserInfo browser_info;
browser_info.socket_name = base::IntToString(port_);
......@@ -48,16 +50,9 @@ void SelfAsDevice::QueryDeviceInfo(const DeviceInfoCallback& callback) {
FROM_HERE, base::Bind(callback, device_info));
}
static void RunSocketCallback(
const AndroidDeviceManager::SocketCallback& callback,
net::StreamSocket* socket,
int result) {
callback.Run(result, socket);
}
void SelfAsDevice::OpenSocket(const std::string& socket_name,
const SocketCallback& callback) {
DCHECK(CalledOnValidThread());
void SelfAsDeviceProvider::OpenSocket(const std::string& serial,
const std::string& socket_name,
const SocketCallback& callback) {
// Use plain socket for remote debugging and port forwarding on Desktop
// (debugging purposes).
net::IPAddressNumber ip_number;
......@@ -70,15 +65,3 @@ void SelfAsDevice::OpenSocket(const std::string& socket_name,
address_list, NULL, net::NetLog::Source());
socket->Connect(base::Bind(&RunSocketCallback, callback, socket));
}
} // namespace
SelfAsDeviceProvider::SelfAsDeviceProvider(int port)
: port_(port) {
}
void SelfAsDeviceProvider::QueryDevices(const QueryDevicesCallback& callback) {
AndroidDeviceManager::Devices result;
result.push_back(new SelfAsDevice(port_));
callback.Run(result);
}
......@@ -12,7 +12,14 @@ class SelfAsDeviceProvider : public AndroidDeviceManager::DeviceProvider {
public:
explicit SelfAsDeviceProvider(int port);
virtual void QueryDevices(const QueryDevicesCallback& callback) OVERRIDE;
virtual void QueryDevices(const SerialsCallback& callback) OVERRIDE;
virtual void QueryDeviceInfo(const std::string& serial,
const DeviceInfoCallback& callback) OVERRIDE;
virtual void OpenSocket(const std::string& serial,
const std::string& socket_name,
const SocketCallback& callback) OVERRIDE;
private:
virtual ~SelfAsDeviceProvider(){}
......
......@@ -18,123 +18,59 @@ const char kLocalAbstractCommand[] = "localabstract:%s";
const int kBufferSize = 16 * 1024;
class UsbDeviceImpl : public AndroidDeviceManager::Device {
public:
explicit UsbDeviceImpl(AndroidUsbDevice* device);
virtual void QueryDeviceInfo(const DeviceInfoCallback& callback) OVERRIDE;
virtual void OpenSocket(const std::string& name,
const SocketCallback& callback) OVERRIDE;
private:
void OnOpenSocket(const SocketCallback& callback,
net::StreamSocket* socket,
int result);
void RunCommand(const std::string& command,
const CommandCallback& callback);
void OpenedForCommand(const CommandCallback& callback,
net::StreamSocket* socket,
int result);
void OnRead(net::StreamSocket* socket,
scoped_refptr<net::IOBuffer> buffer,
const std::string& data,
const CommandCallback& callback,
int result);
virtual ~UsbDeviceImpl() {}
scoped_refptr<AndroidUsbDevice> device_;
};
UsbDeviceImpl::UsbDeviceImpl(AndroidUsbDevice* device)
: Device(device->serial(), device->is_connected()),
device_(device) {
device_->InitOnCallerThread();
}
void UsbDeviceImpl::QueryDeviceInfo(const DeviceInfoCallback& callback) {
AdbDeviceInfoQuery::Start(
base::Bind(&UsbDeviceImpl::RunCommand, this), callback);
}
void UsbDeviceImpl::OpenSocket(const std::string& name,
const SocketCallback& callback) {
DCHECK(CalledOnValidThread());
std::string socket_name =
base::StringPrintf(kLocalAbstractCommand, name.c_str());
net::StreamSocket* socket = device_->CreateSocket(socket_name);
if (!socket) {
callback.Run(net::ERR_CONNECTION_FAILED, NULL);
return;
}
int result = socket->Connect(base::Bind(&UsbDeviceImpl::OnOpenSocket, this,
callback, socket));
if (result != net::ERR_IO_PENDING)
callback.Run(result, NULL);
}
void UsbDeviceImpl::OnOpenSocket(const SocketCallback& callback,
void OnOpenSocket(const UsbDeviceProvider::SocketCallback& callback,
net::StreamSocket* socket,
int result) {
callback.Run(result, result == net::OK ? socket : NULL);
}
void UsbDeviceImpl::RunCommand(const std::string& command,
const CommandCallback& callback) {
DCHECK(CalledOnValidThread());
net::StreamSocket* socket = device_->CreateSocket(command);
if (!socket) {
callback.Run(net::ERR_CONNECTION_FAILED, std::string());
void OnRead(net::StreamSocket* socket,
scoped_refptr<net::IOBuffer> 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;
}
int result = socket->Connect(base::Bind(&UsbDeviceImpl::OpenedForCommand,
this, callback, socket));
std::string new_data = data + std::string(buffer->data(), result);
result =
socket->Read(buffer,
kBufferSize,
base::Bind(&OnRead, socket, buffer, new_data, callback));
if (result != net::ERR_IO_PENDING)
callback.Run(result, std::string());
OnRead(socket, buffer, new_data, callback, result);
}
void UsbDeviceImpl::OpenedForCommand(const CommandCallback& callback,
net::StreamSocket* socket,
int result) {
void OpenedForCommand(const UsbDeviceProvider::CommandCallback& callback,
net::StreamSocket* socket,
int result) {
if (result != net::OK) {
callback.Run(result, std::string());
return;
}
scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kBufferSize);
result = socket->Read(buffer, kBufferSize,
base::Bind(&UsbDeviceImpl::OnRead, this,
socket, buffer, std::string(), callback));
result = socket->Read(
buffer,
kBufferSize,
base::Bind(&OnRead, socket, buffer, std::string(), callback));
if (result != net::ERR_IO_PENDING)
OnRead(socket, buffer, std::string(), callback, result);
}
void UsbDeviceImpl::OnRead(net::StreamSocket* socket,
scoped_refptr<net::IOBuffer> buffer,
const std::string& data,
const CommandCallback& callback,
int result) {
if (result <= 0) {
callback.Run(result, result == 0 ? data : std::string());
delete socket;
void RunCommand(scoped_refptr<AndroidUsbDevice> 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;
}
std::string new_data = data + std::string(buffer->data(), result);
result = socket->Read(buffer, kBufferSize,
base::Bind(&UsbDeviceImpl::OnRead, this,
socket, buffer, new_data, callback));
int result = socket->Connect(base::Bind(&OpenedForCommand, callback, socket));
if (result != net::ERR_IO_PENDING)
OnRead(socket, buffer, new_data, callback, result);
}
static void EnumeratedDevices(
const UsbDeviceProvider::QueryDevicesCallback& callback,
const AndroidUsbDevices& devices) {
AndroidDeviceManager::Devices result;
for (AndroidUsbDevices::const_iterator it = devices.begin();
it != devices.end(); ++it)
result.push_back(new UsbDeviceImpl(*it));
callback.Run(result);
callback.Run(result, std::string());
}
} // namespace
......@@ -149,10 +85,60 @@ 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::QueryDevices(const QueryDevicesCallback& callback) {
AndroidUsbDevice::Enumerate(
rsa_key_.get(), base::Bind(&EnumeratedDevices, callback));
void UsbDeviceProvider::EnumeratedDevices(const SerialsCallback& callback,
const AndroidUsbDevices& devices) {
std::vector<std::string> 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);
}
......@@ -11,20 +11,36 @@ namespace crypto {
class RSAPrivateKey;
}
class AndroidUsbDevice;
class UsbDeviceProvider : public AndroidDeviceManager::DeviceProvider {
public:
typedef DeviceProvider::QueryDevicesCallback QueryDevicesCallback;
static void CountDevices(const base::Callback<void(int)>& callback);
explicit UsbDeviceProvider(Profile* profile);
virtual void QueryDevices(const QueryDevicesCallback& callback) OVERRIDE;
virtual void QueryDevices(const SerialsCallback& callback) OVERRIDE;
virtual void QueryDeviceInfo(const std::string& serial,
const DeviceInfoCallback& callback) OVERRIDE;
virtual void OpenSocket(const std::string& serial,
const std::string& socket_name,
const SocketCallback& callback) OVERRIDE;
virtual void ReleaseDevice(const std::string& serial) OVERRIDE;
private:
virtual ~UsbDeviceProvider();
void EnumeratedDevices(
const SerialsCallback& callback,
const std::vector<scoped_refptr<AndroidUsbDevice> >& devices);
typedef std::map<std::string, scoped_refptr<AndroidUsbDevice> > UsbDeviceMap;
scoped_ptr<crypto::RSAPrivateKey> rsa_key_;
UsbDeviceMap device_map_;
};
#endif // CHROME_BROWSER_DEVTOOLS_DEVICE_USB_USB_DEVICE_PROVIDER_H_
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