Manual devtools fixups for scoped_refptr operator T* removal.
[chromium-blink-merge.git] / chrome / browser / devtools / device / usb / android_usb_device.cc
blob3a2bee1d54720fc46e5a9714bc9c8d1f5101e54b
1 // Copyright 2014 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.
5 #include "chrome/browser/devtools/device/usb/android_usb_device.h"
7 #include <set>
9 #include "base/barrier_closure.h"
10 #include "base/base64.h"
11 #include "base/lazy_instance.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/stl_util.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "chrome/browser/devtools/device/usb/android_rsa.h"
18 #include "chrome/browser/devtools/device/usb/android_usb_socket.h"
19 #include "components/usb_service/usb_device.h"
20 #include "components/usb_service/usb_interface.h"
21 #include "components/usb_service/usb_service.h"
22 #include "content/public/browser/browser_thread.h"
23 #include "crypto/rsa_private_key.h"
24 #include "net/base/ip_endpoint.h"
25 #include "net/base/net_errors.h"
26 #include "net/socket/stream_socket.h"
28 using usb_service::UsbConfigDescriptor;
29 using usb_service::UsbDevice;
30 using usb_service::UsbDeviceHandle;
31 using usb_service::UsbInterfaceAltSettingDescriptor;
32 using usb_service::UsbInterfaceDescriptor;
33 using usb_service::UsbEndpointDescriptor;
34 using usb_service::UsbService;
35 using usb_service::UsbTransferStatus;
37 namespace {
39 const size_t kHeaderSize = 24;
41 const int kAdbClass = 0xff;
42 const int kAdbSubclass = 0x42;
43 const int kAdbProtocol = 0x1;
45 const int kUsbTimeout = 0;
47 const uint32 kMaxPayload = 4096;
48 const uint32 kVersion = 0x01000000;
50 static const char kHostConnectMessage[] = "host::";
52 using content::BrowserThread;
54 typedef std::vector<scoped_refptr<UsbDevice> > UsbDevices;
55 typedef std::set<scoped_refptr<UsbDevice> > UsbDeviceSet;
57 // Stores android wrappers around claimed usb devices on caller thread.
58 base::LazyInstance<std::vector<AndroidUsbDevice*> >::Leaky g_devices =
59 LAZY_INSTANCE_INITIALIZER;
61 bool IsAndroidInterface(
62 scoped_refptr<const usb_service::UsbInterfaceDescriptor> interface) {
63 if (interface->GetNumAltSettings() == 0)
64 return false;
66 scoped_refptr<const UsbInterfaceAltSettingDescriptor> idesc =
67 interface->GetAltSetting(0);
69 if (idesc->GetInterfaceClass() != kAdbClass ||
70 idesc->GetInterfaceSubclass() != kAdbSubclass ||
71 idesc->GetInterfaceProtocol() != kAdbProtocol ||
72 idesc->GetNumEndpoints() != 2) {
73 return false;
75 return true;
78 scoped_refptr<AndroidUsbDevice> ClaimInterface(
79 crypto::RSAPrivateKey* rsa_key,
80 scoped_refptr<UsbDeviceHandle> usb_handle,
81 scoped_refptr<const UsbInterfaceDescriptor> interface,
82 int interface_id) {
83 scoped_refptr<const UsbInterfaceAltSettingDescriptor> idesc =
84 interface->GetAltSetting(0);
86 int inbound_address = 0;
87 int outbound_address = 0;
88 int zero_mask = 0;
90 for (size_t i = 0; i < idesc->GetNumEndpoints(); ++i) {
91 scoped_refptr<const UsbEndpointDescriptor> edesc =
92 idesc->GetEndpoint(i);
93 if (edesc->GetTransferType() != usb_service::USB_TRANSFER_BULK)
94 continue;
95 if (edesc->GetDirection() == usb_service::USB_DIRECTION_INBOUND)
96 inbound_address = edesc->GetAddress();
97 else
98 outbound_address = edesc->GetAddress();
99 zero_mask = edesc->GetMaximumPacketSize() - 1;
102 if (inbound_address == 0 || outbound_address == 0)
103 return NULL;
105 if (!usb_handle->ClaimInterface(interface_id))
106 return NULL;
108 base::string16 serial;
109 if (!usb_handle->GetSerial(&serial) || serial.empty())
110 return NULL;
112 return new AndroidUsbDevice(rsa_key, usb_handle, base::UTF16ToASCII(serial),
113 inbound_address, outbound_address, zero_mask,
114 interface_id);
117 uint32 Checksum(const std::string& data) {
118 unsigned char* x = (unsigned char*)data.data();
119 int count = data.length();
120 uint32 sum = 0;
121 while (count-- > 0)
122 sum += *x++;
123 return sum;
126 void DumpMessage(bool outgoing, const char* data, size_t length) {
127 #if 0
128 std::string result = "";
129 if (length == kHeaderSize) {
130 for (size_t i = 0; i < 24; ++i) {
131 result += base::StringPrintf("%02x",
132 data[i] > 0 ? data[i] : (data[i] + 0x100) & 0xFF);
133 if ((i + 1) % 4 == 0)
134 result += " ";
136 for (size_t i = 0; i < 24; ++i) {
137 if (data[i] >= 0x20 && data[i] <= 0x7E)
138 result += data[i];
139 else
140 result += ".";
142 } else {
143 result = base::StringPrintf("%d: ", (int)length);
144 for (size_t i = 0; i < length; ++i) {
145 if (data[i] >= 0x20 && data[i] <= 0x7E)
146 result += data[i];
147 else
148 result += ".";
151 LOG(ERROR) << (outgoing ? "[out] " : "[ in] ") << result;
152 #endif // 0
155 void ReleaseInterface(scoped_refptr<UsbDeviceHandle> usb_device,
156 int interface_id) {
157 usb_device->ReleaseInterface(interface_id);
158 usb_device->Close();
161 } // namespace
163 AdbMessage::AdbMessage(uint32 command,
164 uint32 arg0,
165 uint32 arg1,
166 const std::string& body)
167 : command(command),
168 arg0(arg0),
169 arg1(arg1),
170 body(body) {
173 AdbMessage::~AdbMessage() {
176 static void RespondOnCallerThread(const AndroidUsbDevicesCallback& callback,
177 AndroidUsbDevices* new_devices) {
178 scoped_ptr<AndroidUsbDevices> devices(new_devices);
180 // Add raw pointers to the newly claimed devices.
181 for (AndroidUsbDevices::iterator it = devices->begin(); it != devices->end();
182 ++it) {
183 g_devices.Get().push_back(it->get());
186 // Return all claimed devices.
187 AndroidUsbDevices result(g_devices.Get().begin(), g_devices.Get().end());
188 callback.Run(result);
191 static void RespondOnFileThread(
192 const AndroidUsbDevicesCallback& callback,
193 AndroidUsbDevices* devices,
194 scoped_refptr<base::MessageLoopProxy> caller_message_loop_proxy) {
195 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
196 caller_message_loop_proxy->PostTask(
197 FROM_HERE,
198 base::Bind(&RespondOnCallerThread, callback, devices));
201 static void OpenAndroidDeviceOnFileThread(
202 AndroidUsbDevices* devices,
203 crypto::RSAPrivateKey* rsa_key,
204 const base::Closure& barrier,
205 scoped_refptr<UsbDevice> device,
206 int interface_id,
207 bool success) {
208 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
209 if (success) {
210 scoped_refptr<UsbConfigDescriptor> config = device->ListInterfaces();
211 scoped_refptr<UsbDeviceHandle> usb_handle = device->Open();
212 if (usb_handle.get()) {
213 scoped_refptr<AndroidUsbDevice> android_device =
214 ClaimInterface(rsa_key, usb_handle, config->GetInterface(interface_id),
215 interface_id);
216 if (android_device.get())
217 devices->push_back(android_device.get());
218 else
219 usb_handle->Close();
222 barrier.Run();
225 static int CountOnFileThread() {
226 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
227 UsbService* service = UsbService::GetInstance();
228 UsbDevices usb_devices;
229 if (service != NULL)
230 service->GetDevices(&usb_devices);
231 int device_count = 0;
232 for (UsbDevices::iterator it = usb_devices.begin(); it != usb_devices.end();
233 ++it) {
234 scoped_refptr<UsbConfigDescriptor> config = (*it)->ListInterfaces();
235 if (!config.get())
236 continue;
238 for (size_t j = 0; j < config->GetNumInterfaces(); ++j) {
239 if (IsAndroidInterface(config->GetInterface(j)))
240 ++device_count;
243 return device_count;
246 static void EnumerateOnFileThread(
247 crypto::RSAPrivateKey* rsa_key,
248 const AndroidUsbDevicesCallback& callback,
249 scoped_refptr<base::MessageLoopProxy> caller_message_loop_proxy) {
250 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
252 UsbService* service = UsbService::GetInstance();
253 UsbDevices usb_devices;
254 if (service != NULL)
255 service->GetDevices(&usb_devices);
257 // Add new devices.
258 AndroidUsbDevices* devices = new AndroidUsbDevices();
259 base::Closure barrier = base::BarrierClosure(
260 usb_devices.size(), base::Bind(&RespondOnFileThread,
261 callback,
262 devices,
263 caller_message_loop_proxy));
265 for (UsbDevices::iterator it = usb_devices.begin(); it != usb_devices.end();
266 ++it) {
267 scoped_refptr<UsbConfigDescriptor> config = (*it)->ListInterfaces();
268 if (!config.get()) {
269 barrier.Run();
270 continue;
273 bool has_android_interface = false;
274 for (size_t j = 0; j < config->GetNumInterfaces(); ++j) {
275 if (!IsAndroidInterface(config->GetInterface(j)))
276 continue;
278 // Request permission on Chrome OS.
279 #if defined(OS_CHROMEOS)
280 (*it)->RequestUsbAccess(j, base::Bind(&OpenAndroidDeviceOnFileThread,
281 devices, rsa_key, barrier, *it, j));
282 #else
283 OpenAndroidDeviceOnFileThread(devices, rsa_key, barrier, *it, j, true);
284 #endif // defined(OS_CHROMEOS)
286 has_android_interface = true;
287 break;
289 if (!has_android_interface)
290 barrier.Run();
294 // static
295 void AndroidUsbDevice::CountDevices(
296 const base::Callback<void(int)>& callback) {
297 BrowserThread::PostTaskAndReplyWithResult(
298 BrowserThread::FILE,
299 FROM_HERE,
300 base::Bind(&CountOnFileThread),
301 callback);
304 // static
305 void AndroidUsbDevice::Enumerate(crypto::RSAPrivateKey* rsa_key,
306 const AndroidUsbDevicesCallback& callback) {
308 // Collect devices with closed handles.
309 for (std::vector<AndroidUsbDevice*>::iterator it = g_devices.Get().begin();
310 it != g_devices.Get().end(); ++it) {
311 if ((*it)->usb_handle_.get()) {
312 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
313 base::Bind(&AndroidUsbDevice::TerminateIfReleased, *it,
314 (*it)->usb_handle_));
318 // Then look for the new devices.
319 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
320 base::Bind(&EnumerateOnFileThread, rsa_key, callback,
321 base::MessageLoopProxy::current()));
324 AndroidUsbDevice::AndroidUsbDevice(crypto::RSAPrivateKey* rsa_key,
325 scoped_refptr<UsbDeviceHandle> usb_device,
326 const std::string& serial,
327 int inbound_address,
328 int outbound_address,
329 int zero_mask,
330 int interface_id)
331 : message_loop_(NULL),
332 rsa_key_(rsa_key->Copy()),
333 usb_handle_(usb_device),
334 serial_(serial),
335 inbound_address_(inbound_address),
336 outbound_address_(outbound_address),
337 zero_mask_(zero_mask),
338 interface_id_(interface_id),
339 is_connected_(false),
340 signature_sent_(false),
341 last_socket_id_(256),
342 weak_factory_(this) {
345 void AndroidUsbDevice::InitOnCallerThread() {
346 if (message_loop_)
347 return;
348 message_loop_ = base::MessageLoop::current();
349 Queue(new AdbMessage(AdbMessage::kCommandCNXN, kVersion, kMaxPayload,
350 kHostConnectMessage));
351 ReadHeader();
354 net::StreamSocket* AndroidUsbDevice::CreateSocket(const std::string& command) {
355 if (!usb_handle_.get())
356 return NULL;
358 uint32 socket_id = ++last_socket_id_;
359 sockets_[socket_id] = new AndroidUsbSocket(this, socket_id, command,
360 base::Bind(&AndroidUsbDevice::SocketDeleted, this));
361 return sockets_[socket_id];
364 void AndroidUsbDevice::Send(uint32 command,
365 uint32 arg0,
366 uint32 arg1,
367 const std::string& body) {
368 scoped_refptr<AdbMessage> m = new AdbMessage(command, arg0, arg1, body);
369 // Delay open request if not yet connected.
370 if (!is_connected_) {
371 pending_messages_.push_back(m);
372 return;
374 Queue(m);
377 AndroidUsbDevice::~AndroidUsbDevice() {
378 DCHECK(message_loop_ == base::MessageLoop::current());
379 Terminate();
382 void AndroidUsbDevice::Queue(scoped_refptr<AdbMessage> message) {
383 DCHECK(message_loop_ == base::MessageLoop::current());
385 // Queue header.
386 std::vector<uint32> header;
387 header.push_back(message->command);
388 header.push_back(message->arg0);
389 header.push_back(message->arg1);
390 bool append_zero = true;
391 if (message->body.empty())
392 append_zero = false;
393 if (message->command == AdbMessage::kCommandAUTH &&
394 message->arg0 == AdbMessage::kAuthSignature)
395 append_zero = false;
396 if (message->command == AdbMessage::kCommandWRTE)
397 append_zero = false;
399 size_t body_length = message->body.length() + (append_zero ? 1 : 0);
400 header.push_back(body_length);
401 header.push_back(Checksum(message->body));
402 header.push_back(message->command ^ 0xffffffff);
403 scoped_refptr<net::IOBufferWithSize> header_buffer =
404 new net::IOBufferWithSize(kHeaderSize);
405 memcpy(header_buffer.get()->data(), &header[0], kHeaderSize);
406 outgoing_queue_.push(header_buffer);
408 // Queue body.
409 if (!message->body.empty()) {
410 scoped_refptr<net::IOBufferWithSize> body_buffer =
411 new net::IOBufferWithSize(body_length);
412 memcpy(body_buffer->data(), message->body.data(), message->body.length());
413 if (append_zero)
414 body_buffer->data()[body_length - 1] = 0;
415 outgoing_queue_.push(body_buffer);
416 if (zero_mask_ && (body_length & zero_mask_) == 0) {
417 // Send a zero length packet.
418 outgoing_queue_.push(new net::IOBufferWithSize(0));
421 ProcessOutgoing();
424 void AndroidUsbDevice::ProcessOutgoing() {
425 DCHECK(message_loop_ == base::MessageLoop::current());
427 if (outgoing_queue_.empty() || !usb_handle_.get())
428 return;
430 BulkMessage message = outgoing_queue_.front();
431 outgoing_queue_.pop();
432 DumpMessage(true, message->data(), message->size());
433 usb_handle_->BulkTransfer(usb_service::USB_DIRECTION_OUTBOUND,
434 outbound_address_,
435 message.get(),
436 message->size(),
437 kUsbTimeout,
438 base::Bind(&AndroidUsbDevice::OutgoingMessageSent,
439 weak_factory_.GetWeakPtr()));
442 void AndroidUsbDevice::OutgoingMessageSent(UsbTransferStatus status,
443 scoped_refptr<net::IOBuffer> buffer,
444 size_t result) {
445 DCHECK(message_loop_ == base::MessageLoop::current());
447 if (status != usb_service::USB_TRANSFER_COMPLETED)
448 return;
449 message_loop_->PostTask(FROM_HERE,
450 base::Bind(&AndroidUsbDevice::ProcessOutgoing, this));
453 void AndroidUsbDevice::ReadHeader() {
454 DCHECK(message_loop_ == base::MessageLoop::current());
456 if (!usb_handle_.get())
457 return;
458 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kHeaderSize);
459 usb_handle_->BulkTransfer(
460 usb_service::USB_DIRECTION_INBOUND,
461 inbound_address_,
462 buffer.get(),
463 kHeaderSize,
464 kUsbTimeout,
465 base::Bind(&AndroidUsbDevice::ParseHeader, weak_factory_.GetWeakPtr()));
468 void AndroidUsbDevice::ParseHeader(UsbTransferStatus status,
469 scoped_refptr<net::IOBuffer> buffer,
470 size_t result) {
471 DCHECK(message_loop_ == base::MessageLoop::current());
473 if (status == usb_service::USB_TRANSFER_TIMEOUT) {
474 message_loop_->PostTask(FROM_HERE,
475 base::Bind(&AndroidUsbDevice::ReadHeader, this));
476 return;
479 if (status != usb_service::USB_TRANSFER_COMPLETED || result != kHeaderSize) {
480 TransferError(status);
481 return;
484 DumpMessage(false, buffer->data(), result);
485 std::vector<uint32> header(6);
486 memcpy(&header[0], buffer->data(), result);
487 scoped_refptr<AdbMessage> message =
488 new AdbMessage(header[0], header[1], header[2], "");
489 uint32 data_length = header[3];
490 uint32 data_check = header[4];
491 uint32 magic = header[5];
492 if ((message->command ^ 0xffffffff) != magic) {
493 TransferError(usb_service::USB_TRANSFER_ERROR);
494 return;
497 if (data_length == 0) {
498 message_loop_->PostTask(FROM_HERE,
499 base::Bind(&AndroidUsbDevice::HandleIncoming, this,
500 message));
501 return;
504 message_loop_->PostTask(FROM_HERE,
505 base::Bind(&AndroidUsbDevice::ReadBody, this,
506 message, data_length, data_check));
509 void AndroidUsbDevice::ReadBody(scoped_refptr<AdbMessage> message,
510 uint32 data_length,
511 uint32 data_check) {
512 DCHECK(message_loop_ == base::MessageLoop::current());
514 if (!usb_handle_.get())
515 return;
516 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(data_length);
517 usb_handle_->BulkTransfer(usb_service::USB_DIRECTION_INBOUND,
518 inbound_address_,
519 buffer.get(),
520 data_length,
521 kUsbTimeout,
522 base::Bind(&AndroidUsbDevice::ParseBody,
523 weak_factory_.GetWeakPtr(),
524 message,
525 data_length,
526 data_check));
529 void AndroidUsbDevice::ParseBody(scoped_refptr<AdbMessage> message,
530 uint32 data_length,
531 uint32 data_check,
532 UsbTransferStatus status,
533 scoped_refptr<net::IOBuffer> buffer,
534 size_t result) {
535 DCHECK(message_loop_ == base::MessageLoop::current());
537 if (status == usb_service::USB_TRANSFER_TIMEOUT) {
538 message_loop_->PostTask(FROM_HERE,
539 base::Bind(&AndroidUsbDevice::ReadBody, this,
540 message, data_length, data_check));
541 return;
544 if (status != usb_service::USB_TRANSFER_COMPLETED ||
545 static_cast<uint32>(result) != data_length) {
546 TransferError(status);
547 return;
550 DumpMessage(false, buffer->data(), data_length);
551 message->body = std::string(buffer->data(), result);
552 if (Checksum(message->body) != data_check) {
553 TransferError(usb_service::USB_TRANSFER_ERROR);
554 return;
557 message_loop_->PostTask(FROM_HERE,
558 base::Bind(&AndroidUsbDevice::HandleIncoming, this,
559 message));
562 void AndroidUsbDevice::HandleIncoming(scoped_refptr<AdbMessage> message) {
563 DCHECK(message_loop_ == base::MessageLoop::current());
565 switch (message->command) {
566 case AdbMessage::kCommandAUTH:
568 DCHECK_EQ(message->arg0, static_cast<uint32>(AdbMessage::kAuthToken));
569 if (signature_sent_) {
570 Queue(new AdbMessage(AdbMessage::kCommandAUTH,
571 AdbMessage::kAuthRSAPublicKey, 0,
572 AndroidRSAPublicKey(rsa_key_.get())));
573 } else {
574 signature_sent_ = true;
575 std::string signature = AndroidRSASign(rsa_key_.get(), message->body);
576 if (!signature.empty()) {
577 Queue(new AdbMessage(AdbMessage::kCommandAUTH,
578 AdbMessage::kAuthSignature, 0,
579 signature));
580 } else {
581 Queue(new AdbMessage(AdbMessage::kCommandAUTH,
582 AdbMessage::kAuthRSAPublicKey, 0,
583 AndroidRSAPublicKey(rsa_key_.get())));
587 break;
588 case AdbMessage::kCommandCNXN:
590 is_connected_ = true;
591 PendingMessages pending;
592 pending.swap(pending_messages_);
593 for (PendingMessages::iterator it = pending.begin();
594 it != pending.end(); ++it) {
595 Queue(*it);
598 break;
599 case AdbMessage::kCommandOKAY:
600 case AdbMessage::kCommandWRTE:
601 case AdbMessage::kCommandCLSE:
603 AndroidUsbSockets::iterator it = sockets_.find(message->arg1);
604 if (it != sockets_.end())
605 it->second->HandleIncoming(message);
607 break;
608 default:
609 break;
611 ReadHeader();
614 void AndroidUsbDevice::TransferError(UsbTransferStatus status) {
615 DCHECK(message_loop_ == base::MessageLoop::current());
617 message_loop_->PostTask(FROM_HERE,
618 base::Bind(&AndroidUsbDevice::Terminate, this));
621 void AndroidUsbDevice::TerminateIfReleased(
622 scoped_refptr<UsbDeviceHandle> usb_handle) {
623 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
624 if (usb_handle->GetDevice().get())
625 return;
626 message_loop_->PostTask(FROM_HERE,
627 base::Bind(&AndroidUsbDevice::Terminate, this));
630 void AndroidUsbDevice::Terminate() {
631 DCHECK(message_loop_ == base::MessageLoop::current());
633 std::vector<AndroidUsbDevice*>::iterator it =
634 std::find(g_devices.Get().begin(), g_devices.Get().end(), this);
635 if (it != g_devices.Get().end())
636 g_devices.Get().erase(it);
638 if (!usb_handle_.get())
639 return;
641 // Make sure we zero-out handle so that closing connections did not open
642 // new connections.
643 scoped_refptr<UsbDeviceHandle> usb_handle = usb_handle_;
644 usb_handle_ = NULL;
646 // Iterate over copy.
647 AndroidUsbSockets sockets(sockets_);
648 for (AndroidUsbSockets::iterator it = sockets.begin();
649 it != sockets.end(); ++it) {
650 it->second->Terminated(true);
652 DCHECK(sockets_.empty());
654 BrowserThread::PostTask(
655 BrowserThread::FILE, FROM_HERE,
656 base::Bind(&ReleaseInterface, usb_handle, interface_id_));
659 void AndroidUsbDevice::SocketDeleted(uint32 socket_id) {
660 DCHECK(message_loop_ == base::MessageLoop::current());
662 sockets_.erase(socket_id);