1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/devtools/android_device.h"
6
7 #include "base/strings/string_util.h"
8 #include "base/strings/stringprintf.h"
9 #include "base/threading/thread.h"
10 #include "chrome/browser/devtools/adb/android_rsa.h"
11 #include "chrome/browser/devtools/adb/android_usb_device.h"
12 #include "chrome/browser/devtools/adb_client_socket.h"
13 #include "net/base/net_errors.h"
14
15 using content::BrowserThread;
16
17 namespace {
18
19 const char kHostTransportCommand[] = "host:transport:%s|%s";
20 const char kHostDevicesCommand[] = "host:devices";
21 const char kLocalAbstractCommand[] = "localabstract:%s";
22
23 const int kAdbPort = 5037;
24 const int kBufferSize = 16 * 1024;
25
26 // AdbDeviceImpl --------------------------------------------------------------
27
28 class AdbDeviceImpl : public AndroidDevice {
29 public:
30 AdbDeviceImpl(const std::string& serial, bool is_connected);
31 virtual void RunCommand(const std::string& command,
32 const CommandCallback& callback) OVERRIDE;
33 virtual void OpenSocket(const std::string& name,
34 const SocketCallback& callback) OVERRIDE;
35 private:
~AdbDeviceImpl()36 virtual ~AdbDeviceImpl() {}
37 };
38
AdbDeviceImpl(const std::string & serial,bool is_connected)39 AdbDeviceImpl::AdbDeviceImpl(const std::string& serial, bool is_connected)
40 : AndroidDevice(serial, is_connected) {
41 }
42
RunCommand(const std::string & command,const CommandCallback & callback)43 void AdbDeviceImpl::RunCommand(const std::string& command,
44 const CommandCallback& callback) {
45 std::string query = base::StringPrintf(kHostTransportCommand,
46 serial().c_str(), command.c_str());
47 AdbClientSocket::AdbQuery(kAdbPort, query, callback);
48 }
49
OpenSocket(const std::string & name,const SocketCallback & callback)50 void AdbDeviceImpl::OpenSocket(const std::string& name,
51 const SocketCallback& callback) {
52 std::string socket_name =
53 base::StringPrintf(kLocalAbstractCommand, name.c_str());
54 AdbClientSocket::TransportQuery(kAdbPort, serial(), socket_name, callback);
55 }
56
57 // UsbDeviceImpl --------------------------------------------------------------
58
59 class UsbDeviceImpl : public AndroidDevice {
60 public:
61 explicit UsbDeviceImpl(AndroidUsbDevice* device);
62 virtual void RunCommand(const std::string& command,
63 const CommandCallback& callback) OVERRIDE;
64 virtual void OpenSocket(const std::string& name,
65 const SocketCallback& callback) OVERRIDE;
66 private:
67 void OnOpenSocket(const SocketCallback& callback,
68 net::StreamSocket* socket,
69 int result);
70 void OpenedForCommand(const CommandCallback& callback,
71 net::StreamSocket* socket,
72 int result);
73 void OnRead(net::StreamSocket* socket,
74 scoped_refptr<net::IOBuffer> buffer,
75 const std::string& data,
76 const CommandCallback& callback,
77 int result);
78
~UsbDeviceImpl()79 virtual ~UsbDeviceImpl() {}
80 scoped_refptr<AndroidUsbDevice> device_;
81 };
82
83
UsbDeviceImpl(AndroidUsbDevice * device)84 UsbDeviceImpl::UsbDeviceImpl(AndroidUsbDevice* device)
85 : AndroidDevice(device->serial(), device->is_connected()),
86 device_(device) {
87 device_->InitOnCallerThread();
88 }
89
RunCommand(const std::string & command,const CommandCallback & callback)90 void UsbDeviceImpl::RunCommand(const std::string& command,
91 const CommandCallback& callback) {
92 net::StreamSocket* socket = device_->CreateSocket(command);
93 int result = socket->Connect(base::Bind(&UsbDeviceImpl::OpenedForCommand,
94 this, callback, socket));
95 if (result != net::ERR_IO_PENDING)
96 callback.Run(result, std::string());
97 }
98
OpenSocket(const std::string & name,const SocketCallback & callback)99 void UsbDeviceImpl::OpenSocket(const std::string& name,
100 const SocketCallback& callback) {
101 std::string socket_name =
102 base::StringPrintf(kLocalAbstractCommand, name.c_str());
103 net::StreamSocket* socket = device_->CreateSocket(socket_name);
104 int result = socket->Connect(base::Bind(&UsbDeviceImpl::OnOpenSocket, this,
105 callback, socket));
106 if (result != net::ERR_IO_PENDING)
107 callback.Run(result, NULL);
108 }
109
OnOpenSocket(const SocketCallback & callback,net::StreamSocket * socket,int result)110 void UsbDeviceImpl::OnOpenSocket(const SocketCallback& callback,
111 net::StreamSocket* socket,
112 int result) {
113 callback.Run(result, result == net::OK ? socket : NULL);
114 }
115
OpenedForCommand(const CommandCallback & callback,net::StreamSocket * socket,int result)116 void UsbDeviceImpl::OpenedForCommand(const CommandCallback& callback,
117 net::StreamSocket* socket,
118 int result) {
119 if (result != net::OK) {
120 callback.Run(result, std::string());
121 return;
122 }
123 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kBufferSize);
124 result = socket->Read(buffer, kBufferSize,
125 base::Bind(&UsbDeviceImpl::OnRead, this,
126 socket, buffer, std::string(), callback));
127 if (result != net::ERR_IO_PENDING)
128 OnRead(socket, buffer, std::string(), callback, result);
129 }
130
OnRead(net::StreamSocket * socket,scoped_refptr<net::IOBuffer> buffer,const std::string & data,const CommandCallback & callback,int result)131 void UsbDeviceImpl::OnRead(net::StreamSocket* socket,
132 scoped_refptr<net::IOBuffer> buffer,
133 const std::string& data,
134 const CommandCallback& callback,
135 int result) {
136 if (result <= 0) {
137 callback.Run(result, result == 0 ? data : std::string());
138 delete socket;
139 return;
140 }
141
142 std::string new_data = data + std::string(buffer->data(), result);
143 result = socket->Read(buffer, kBufferSize,
144 base::Bind(&UsbDeviceImpl::OnRead, this,
145 socket, buffer, new_data, callback));
146 if (result != net::ERR_IO_PENDING)
147 OnRead(socket, buffer, new_data, callback, result);
148 }
149
150 // AdbDeviceProvider -------------------------------------------
151
152 class AdbDeviceProvider: public AndroidDeviceProvider {
153 public:
154 virtual void QueryDevices(const QueryDevicesCallback& callback) OVERRIDE;
155 private:
156 void QueryDevicesOnAdbThread(const QueryDevicesCallback& callback);
157 void ReceivedAdbDevices(const QueryDevicesCallback& callback, int result,
158 const std::string& response);
159
160 virtual ~AdbDeviceProvider();
161 };
162
~AdbDeviceProvider()163 AdbDeviceProvider::~AdbDeviceProvider() {
164 }
165
QueryDevices(const QueryDevicesCallback & callback)166 void AdbDeviceProvider::QueryDevices(const QueryDevicesCallback& callback) {
167 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
168
169 adb_thread_->message_loop()->PostTask(
170 FROM_HERE, base::Bind(&AdbDeviceProvider::QueryDevicesOnAdbThread,
171 this, callback));
172 }
173
QueryDevicesOnAdbThread(const QueryDevicesCallback & callback)174 void AdbDeviceProvider::QueryDevicesOnAdbThread(
175 const QueryDevicesCallback& callback) {
176 DCHECK_EQ(adb_thread_->message_loop(), base::MessageLoop::current());
177
178 AdbClientSocket::AdbQuery(
179 kAdbPort, kHostDevicesCommand,
180 base::Bind(&AdbDeviceProvider::ReceivedAdbDevices, this, callback));
181 }
182
ReceivedAdbDevices(const QueryDevicesCallback & callback,int result_code,const std::string & response)183 void AdbDeviceProvider::ReceivedAdbDevices(const QueryDevicesCallback& callback,
184 int result_code,
185 const std::string& response) {
186 DCHECK_EQ(adb_thread_->message_loop(), base::MessageLoop::current());
187
188 AndroidDevices result;
189
190 #if defined(DEBUG_DEVTOOLS)
191 // For desktop remote debugging.
192 result.push_back(new AdbDeviceImpl("", true));
193 #endif // defined(DEBUG_DEVTOOLS)
194
195 std::vector<std::string> serials;
196 Tokenize(response, "\n", &serials);
197 for (size_t i = 0; i < serials.size(); ++i) {
198 std::vector<std::string> tokens;
199 Tokenize(serials[i], "\t ", &tokens);
200 bool offline = tokens.size() > 1 && tokens[1] == "offline";
201 result.push_back(new AdbDeviceImpl(tokens[0], !offline));
202 }
203
204 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
205 base::Bind(&AdbDeviceProvider::RunCallbackOnUIThread,
206 callback, result));
207 }
208
209 // UsbDeviceProvider -------------------------------------------
210
211 class UsbDeviceProvider: public AndroidDeviceProvider {
212 public:
213 explicit UsbDeviceProvider(Profile* profile);
214
215 virtual void QueryDevices(const QueryDevicesCallback& callback) OVERRIDE;
216 private:
217 virtual ~UsbDeviceProvider();
218 void WrapDevicesOnAdbThread(const QueryDevicesCallback& callback,
219 const AndroidUsbDevices& devices);
220 void EnumeratedDevices(const QueryDevicesCallback& callback,
221 const AndroidUsbDevices& devices);
222
223 scoped_ptr<crypto::RSAPrivateKey> rsa_key_;
224 };
225
UsbDeviceProvider(Profile * profile)226 UsbDeviceProvider::UsbDeviceProvider(Profile* profile){
227 rsa_key_.reset(AndroidRSAPrivateKey(profile));
228 }
229
~UsbDeviceProvider()230 UsbDeviceProvider::~UsbDeviceProvider() {
231 }
232
QueryDevices(const QueryDevicesCallback & callback)233 void UsbDeviceProvider::QueryDevices(const QueryDevicesCallback& callback) {
234 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
235 AndroidUsbDevice::Enumerate(rsa_key_.get(),
236 base::Bind(&UsbDeviceProvider::EnumeratedDevices,
237 this, callback));
238 }
239
EnumeratedDevices(const QueryDevicesCallback & callback,const AndroidUsbDevices & devices)240 void UsbDeviceProvider::EnumeratedDevices(const QueryDevicesCallback& callback,
241 const AndroidUsbDevices& devices) {
242 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
243 adb_thread_->message_loop()->PostTask(FROM_HERE,
244 base::Bind(&UsbDeviceProvider::WrapDevicesOnAdbThread,
245 this, callback, devices));
246 }
247
WrapDevicesOnAdbThread(const QueryDevicesCallback & callback,const AndroidUsbDevices & devices)248 void UsbDeviceProvider::WrapDevicesOnAdbThread(
249 const QueryDevicesCallback& callback,const AndroidUsbDevices& devices) {
250 DCHECK_EQ(adb_thread_->message_loop(), base::MessageLoop::current());
251 AndroidDevices result;
252 for (AndroidUsbDevices::const_iterator it = devices.begin();
253 it != devices.end(); ++it)
254 result.push_back(new UsbDeviceImpl(*it));
255
256 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
257 base::Bind(&UsbDeviceProvider::RunCallbackOnUIThread,
258 callback, result));
259 }
260
261 } // namespace
262
263 // AndroidDevice -------------------------------------------
264
AndroidDevice(const std::string & serial,bool is_connected)265 AndroidDevice::AndroidDevice(const std::string& serial, bool is_connected)
266 : serial_(serial),
267 is_connected_(is_connected) {
268 }
269
HttpQuery(const std::string & la_name,const std::string & request,const CommandCallback & callback)270 void AndroidDevice::HttpQuery(
271 const std::string& la_name,
272 const std::string& request,
273 const CommandCallback& callback) {
274 OpenSocket(la_name, base::Bind(&AndroidDevice::OnHttpSocketOpened, this,
275 request, callback));
276 }
277
HttpUpgrade(const std::string & la_name,const std::string & request,const SocketCallback & callback)278 void AndroidDevice::HttpUpgrade(
279 const std::string& la_name,
280 const std::string& request,
281 const SocketCallback& callback) {
282 OpenSocket(la_name, base::Bind(&AndroidDevice::OnHttpSocketOpened2, this,
283 request, callback));
284 }
285
~AndroidDevice()286 AndroidDevice::~AndroidDevice() {
287 }
288
OnHttpSocketOpened(const std::string & request,const CommandCallback & callback,int result,net::StreamSocket * socket)289 void AndroidDevice::OnHttpSocketOpened(
290 const std::string& request,
291 const CommandCallback& callback,
292 int result,
293 net::StreamSocket* socket) {
294 if (result != net::OK) {
295 callback.Run(result, std::string());
296 return;
297 }
298 AdbClientSocket::HttpQuery(socket, request, callback);
299 }
300
OnHttpSocketOpened2(const std::string & request,const SocketCallback & callback,int result,net::StreamSocket * socket)301 void AndroidDevice::OnHttpSocketOpened2(
302 const std::string& request,
303 const SocketCallback& callback,
304 int result,
305 net::StreamSocket* socket) {
306 if (result != net::OK) {
307 callback.Run(result, NULL);
308 return;
309 }
310 AdbClientSocket::HttpQuery(socket, request, callback);
311 }
312
313 // AdbCountDevicesCommand -----------------------------------------------------
314 // TODO(zvorygin): Remove this class.
315 class AdbCountDevicesCommand : public base::RefCountedThreadSafe<
316 AdbCountDevicesCommand, BrowserThread::DeleteOnUIThread> {
317 public:
318 typedef base::Callback<void(int)> Callback;
319
320 AdbCountDevicesCommand(
321 scoped_refptr<RefCountedAdbThread> adb_thread,
322 const Callback& callback);
323
324 private:
325 friend struct BrowserThread::DeleteOnThread<
326 BrowserThread::UI>;
327 friend class base::DeleteHelper<AdbCountDevicesCommand>;
328
329 virtual ~AdbCountDevicesCommand();
330 void RequestAdbDeviceCount();
331 void ReceivedAdbDeviceCount(int result, const std::string& response);
332 void Respond(int count);
333
334 scoped_refptr<RefCountedAdbThread> adb_thread_;
335 Callback callback_;
336 };
337
AdbCountDevicesCommand(scoped_refptr<RefCountedAdbThread> adb_thread,const Callback & callback)338 AdbCountDevicesCommand::AdbCountDevicesCommand(
339 scoped_refptr<RefCountedAdbThread> adb_thread,
340 const Callback& callback)
341 : adb_thread_(adb_thread),
342 callback_(callback) {
343 adb_thread_->message_loop()->PostTask(
344 FROM_HERE, base::Bind(&AdbCountDevicesCommand::RequestAdbDeviceCount,
345 this));
346 }
347
~AdbCountDevicesCommand()348 AdbCountDevicesCommand::~AdbCountDevicesCommand() {
349 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
350 }
351
RequestAdbDeviceCount()352 void AdbCountDevicesCommand::RequestAdbDeviceCount() {
353 DCHECK_EQ(adb_thread_->message_loop(), base::MessageLoop::current());
354 AdbClientSocket::AdbQuery(
355 kAdbPort, kHostDevicesCommand,
356 base::Bind(&AdbCountDevicesCommand::ReceivedAdbDeviceCount, this));
357 }
358
ReceivedAdbDeviceCount(int result,const std::string & response)359 void AdbCountDevicesCommand::ReceivedAdbDeviceCount(
360 int result,
361 const std::string& response) {
362 DCHECK_EQ(adb_thread_->message_loop(), base::MessageLoop::current());
363 std::vector<std::string> serials;
364 Tokenize(response, "\n", &serials);
365 BrowserThread::PostTask(
366 BrowserThread::UI, FROM_HERE,
367 base::Bind(&AdbCountDevicesCommand::Respond, this, serials.size()));
368 }
369
Respond(int count)370 void AdbCountDevicesCommand::Respond(int count) {
371 callback_.Run(count);
372 }
373
374 // AndroidDeviceProvider ---------------------------------------------------
375
AndroidDeviceProvider()376 AndroidDeviceProvider::AndroidDeviceProvider()
377 : adb_thread_(RefCountedAdbThread::GetInstance()) {
378
379 }
380
~AndroidDeviceProvider()381 AndroidDeviceProvider::~AndroidDeviceProvider() {
382 }
383
384 // static
RunCallbackOnUIThread(const QueryDevicesCallback & callback,const AndroidDevices & result)385 void AndroidDeviceProvider::RunCallbackOnUIThread(
386 const QueryDevicesCallback& callback,
387 const AndroidDevices& result) {
388 callback.Run(result);
389 }
390
391 // static
CountDevices(bool discover_usb_devices,const base::Callback<void (int)> & callback)392 void AndroidDeviceProvider::CountDevices(bool discover_usb_devices,
393 const base::Callback<void(int)>& callback) {
394 if (discover_usb_devices) {
395 AndroidUsbDevice::CountDevices(callback);
396 return;
397 }
398
399 new AdbCountDevicesCommand(RefCountedAdbThread::GetInstance(), callback);
400 }
401
402 // static
403 scoped_refptr<AndroidDeviceProvider>
GetUsbDeviceProvider(Profile * profile)404 AndroidDeviceProvider::GetUsbDeviceProvider(Profile* profile) {
405 return new UsbDeviceProvider(profile);
406 }
407
408 // static
409 scoped_refptr<AndroidDeviceProvider>
GetAdbDeviceProvider()410 AndroidDeviceProvider::GetAdbDeviceProvider() {
411 return new AdbDeviceProvider();
412 }
413