[Cronet] Delay StartNetLog and StopNetLog until native request context is initialized
[chromium-blink-merge.git] / chrome / browser / devtools / device / usb / android_usb_device.cc
blob4ced939f631d8a2724ec128f8c07e3f57e386881
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 "content/public/browser/browser_thread.h"
20 #include "crypto/rsa_private_key.h"
21 #include "device/core/device_client.h"
22 #include "device/usb/usb_descriptors.h"
23 #include "device/usb/usb_device.h"
24 #include "device/usb/usb_service.h"
25 #include "net/base/ip_endpoint.h"
26 #include "net/base/net_errors.h"
27 #include "net/socket/stream_socket.h"
29 using device::UsbConfigDescriptor;
30 using device::UsbDevice;
31 using device::UsbDeviceHandle;
32 using device::UsbInterfaceDescriptor;
33 using device::UsbEndpointDescriptor;
34 using device::UsbService;
35 using device::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(const UsbInterfaceDescriptor& interface) {
62 if (interface.alternate_setting != 0 ||
63 interface.interface_class != kAdbClass ||
64 interface.interface_subclass != kAdbSubclass ||
65 interface.interface_protocol != kAdbProtocol ||
66 interface.endpoints.size() != 2) {
67 return false;
69 return true;
72 scoped_refptr<AndroidUsbDevice> ClaimInterface(
73 crypto::RSAPrivateKey* rsa_key,
74 scoped_refptr<UsbDeviceHandle> usb_handle,
75 const base::string16& serial,
76 const UsbInterfaceDescriptor& interface) {
77 int inbound_address = 0;
78 int outbound_address = 0;
79 int zero_mask = 0;
81 for (const UsbEndpointDescriptor& endpoint : interface.endpoints) {
82 if (endpoint.transfer_type != device::USB_TRANSFER_BULK)
83 continue;
84 if (endpoint.direction == device::USB_DIRECTION_INBOUND)
85 inbound_address = endpoint.address;
86 else
87 outbound_address = endpoint.address;
88 zero_mask = endpoint.maximum_packet_size - 1;
91 if (inbound_address == 0 || outbound_address == 0)
92 return NULL;
94 if (!usb_handle->ClaimInterface(interface.interface_number))
95 return NULL;
97 return new AndroidUsbDevice(rsa_key,
98 usb_handle,
99 base::UTF16ToASCII(serial),
100 inbound_address,
101 outbound_address,
102 zero_mask,
103 interface.interface_number);
106 uint32 Checksum(const std::string& data) {
107 unsigned char* x = (unsigned char*)data.data();
108 int count = data.length();
109 uint32 sum = 0;
110 while (count-- > 0)
111 sum += *x++;
112 return sum;
115 void DumpMessage(bool outgoing, const char* data, size_t length) {
116 #if 0
117 std::string result = "";
118 if (length == kHeaderSize) {
119 for (size_t i = 0; i < 24; ++i) {
120 result += base::StringPrintf("%02x",
121 data[i] > 0 ? data[i] : (data[i] + 0x100) & 0xFF);
122 if ((i + 1) % 4 == 0)
123 result += " ";
125 for (size_t i = 0; i < 24; ++i) {
126 if (data[i] >= 0x20 && data[i] <= 0x7E)
127 result += data[i];
128 else
129 result += ".";
131 } else {
132 result = base::StringPrintf("%d: ", (int)length);
133 for (size_t i = 0; i < length; ++i) {
134 if (data[i] >= 0x20 && data[i] <= 0x7E)
135 result += data[i];
136 else
137 result += ".";
140 LOG(ERROR) << (outgoing ? "[out] " : "[ in] ") << result;
141 #endif // 0
144 void ReleaseInterface(scoped_refptr<UsbDeviceHandle> usb_device,
145 int interface_id) {
146 usb_device->ReleaseInterface(interface_id);
147 usb_device->Close();
150 } // namespace
152 AdbMessage::AdbMessage(uint32 command,
153 uint32 arg0,
154 uint32 arg1,
155 const std::string& body)
156 : command(command),
157 arg0(arg0),
158 arg1(arg1),
159 body(body) {
162 AdbMessage::~AdbMessage() {
165 static void RespondOnCallerThread(const AndroidUsbDevicesCallback& callback,
166 AndroidUsbDevices* new_devices) {
167 scoped_ptr<AndroidUsbDevices> devices(new_devices);
169 // Add raw pointers to the newly claimed devices.
170 for (const scoped_refptr<AndroidUsbDevice>& device : *devices) {
171 g_devices.Get().push_back(device.get());
174 // Return all claimed devices.
175 AndroidUsbDevices result(g_devices.Get().begin(), g_devices.Get().end());
176 callback.Run(result);
179 static void RespondOnFileThread(
180 const AndroidUsbDevicesCallback& callback,
181 AndroidUsbDevices* devices,
182 scoped_refptr<base::MessageLoopProxy> caller_message_loop_proxy) {
183 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
184 caller_message_loop_proxy->PostTask(
185 FROM_HERE,
186 base::Bind(&RespondOnCallerThread, callback, devices));
189 static void OpenAndroidDeviceOnFileThread(
190 AndroidUsbDevices* devices,
191 crypto::RSAPrivateKey* rsa_key,
192 const base::Closure& barrier,
193 scoped_refptr<UsbDevice> device,
194 int interface_id,
195 bool success) {
196 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
197 if (success) {
198 base::string16 serial;
199 if (device->GetSerialNumber(&serial) && !serial.empty()) {
200 const UsbConfigDescriptor* config = device->GetConfiguration();
201 if (config) {
202 scoped_refptr<UsbDeviceHandle> usb_handle = device->Open();
203 if (usb_handle.get()) {
204 scoped_refptr<AndroidUsbDevice> android_device = ClaimInterface(
205 rsa_key, usb_handle, serial, config->interfaces[interface_id]);
206 if (android_device.get())
207 devices->push_back(android_device);
208 else
209 usb_handle->Close();
214 barrier.Run();
217 static int CountOnFileThread() {
218 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
219 UsbService* service = device::DeviceClient::Get()->GetUsbService();
220 UsbDevices usb_devices;
221 if (service != NULL)
222 service->GetDevices(&usb_devices);
223 int device_count = 0;
224 for (const scoped_refptr<UsbDevice>& device : usb_devices) {
225 const UsbConfigDescriptor* config = device->GetConfiguration();
226 if (config) {
227 for (const UsbInterfaceDescriptor& iface : config->interfaces) {
228 if (IsAndroidInterface(iface)) {
229 ++device_count;
234 return device_count;
237 static void EnumerateOnFileThread(
238 crypto::RSAPrivateKey* rsa_key,
239 const AndroidUsbDevicesCallback& callback,
240 scoped_refptr<base::MessageLoopProxy> caller_message_loop_proxy) {
241 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
243 UsbService* service = device::DeviceClient::Get()->GetUsbService();
244 UsbDevices usb_devices;
245 if (service != NULL)
246 service->GetDevices(&usb_devices);
248 // Add new devices.
249 AndroidUsbDevices* devices = new AndroidUsbDevices();
250 base::Closure barrier = base::BarrierClosure(
251 usb_devices.size(), base::Bind(&RespondOnFileThread,
252 callback,
253 devices,
254 caller_message_loop_proxy));
256 for (const scoped_refptr<UsbDevice>& device : usb_devices) {
257 const UsbConfigDescriptor* config = device->GetConfiguration();
258 if (!config) {
259 barrier.Run();
260 continue;
262 bool has_android_interface = false;
263 for (size_t j = 0; j < config->interfaces.size(); ++j) {
264 if (!IsAndroidInterface(config->interfaces[j])) {
265 continue;
268 // Request permission on Chrome OS.
269 #if defined(OS_CHROMEOS)
270 device->RequestUsbAccess(
271 j, base::Bind(&OpenAndroidDeviceOnFileThread, devices, rsa_key,
272 barrier, device, j));
273 #else
274 OpenAndroidDeviceOnFileThread(devices, rsa_key, barrier, device, j, true);
275 #endif // defined(OS_CHROMEOS)
277 has_android_interface = true;
278 break;
280 if (!has_android_interface)
281 barrier.Run();
285 // static
286 void AndroidUsbDevice::CountDevices(
287 const base::Callback<void(int)>& callback) {
288 BrowserThread::PostTaskAndReplyWithResult(
289 BrowserThread::FILE,
290 FROM_HERE,
291 base::Bind(&CountOnFileThread),
292 callback);
295 // static
296 void AndroidUsbDevice::Enumerate(crypto::RSAPrivateKey* rsa_key,
297 const AndroidUsbDevicesCallback& callback) {
299 // Collect devices with closed handles.
300 for (AndroidUsbDevice* device : g_devices.Get()) {
301 if (device->usb_handle_.get()) {
302 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
303 base::Bind(&AndroidUsbDevice::TerminateIfReleased, device,
304 device->usb_handle_));
308 // Then look for the new devices.
309 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
310 base::Bind(&EnumerateOnFileThread, rsa_key, callback,
311 base::MessageLoopProxy::current()));
314 AndroidUsbDevice::AndroidUsbDevice(crypto::RSAPrivateKey* rsa_key,
315 scoped_refptr<UsbDeviceHandle> usb_device,
316 const std::string& serial,
317 int inbound_address,
318 int outbound_address,
319 int zero_mask,
320 int interface_id)
321 : message_loop_(NULL),
322 rsa_key_(rsa_key->Copy()),
323 usb_handle_(usb_device),
324 serial_(serial),
325 inbound_address_(inbound_address),
326 outbound_address_(outbound_address),
327 zero_mask_(zero_mask),
328 interface_id_(interface_id),
329 is_connected_(false),
330 signature_sent_(false),
331 last_socket_id_(256),
332 weak_factory_(this) {
335 void AndroidUsbDevice::InitOnCallerThread() {
336 if (message_loop_)
337 return;
338 message_loop_ = base::MessageLoop::current();
339 Queue(make_scoped_ptr(new AdbMessage(AdbMessage::kCommandCNXN, kVersion,
340 kMaxPayload, kHostConnectMessage)));
341 ReadHeader();
344 net::StreamSocket* AndroidUsbDevice::CreateSocket(const std::string& command) {
345 if (!usb_handle_.get())
346 return NULL;
348 uint32 socket_id = ++last_socket_id_;
349 sockets_[socket_id] = new AndroidUsbSocket(this, socket_id, command,
350 base::Bind(&AndroidUsbDevice::SocketDeleted, this, socket_id));
351 return sockets_[socket_id];
354 void AndroidUsbDevice::Send(uint32 command,
355 uint32 arg0,
356 uint32 arg1,
357 const std::string& body) {
358 scoped_ptr<AdbMessage> message(new AdbMessage(command, arg0, arg1, body));
359 // Delay open request if not yet connected.
360 if (!is_connected_) {
361 pending_messages_.push_back(message.release());
362 return;
364 Queue(message.Pass());
367 AndroidUsbDevice::~AndroidUsbDevice() {
368 DCHECK(message_loop_ == base::MessageLoop::current());
369 Terminate();
372 void AndroidUsbDevice::Queue(scoped_ptr<AdbMessage> message) {
373 DCHECK(message_loop_ == base::MessageLoop::current());
375 // Queue header.
376 std::vector<uint32> header;
377 header.push_back(message->command);
378 header.push_back(message->arg0);
379 header.push_back(message->arg1);
380 bool append_zero = true;
381 if (message->body.empty())
382 append_zero = false;
383 if (message->command == AdbMessage::kCommandAUTH &&
384 message->arg0 == AdbMessage::kAuthSignature)
385 append_zero = false;
386 if (message->command == AdbMessage::kCommandWRTE)
387 append_zero = false;
389 size_t body_length = message->body.length() + (append_zero ? 1 : 0);
390 header.push_back(body_length);
391 header.push_back(Checksum(message->body));
392 header.push_back(message->command ^ 0xffffffff);
393 scoped_refptr<net::IOBufferWithSize> header_buffer =
394 new net::IOBufferWithSize(kHeaderSize);
395 memcpy(header_buffer.get()->data(), &header[0], kHeaderSize);
396 outgoing_queue_.push(header_buffer);
398 // Queue body.
399 if (!message->body.empty()) {
400 scoped_refptr<net::IOBufferWithSize> body_buffer =
401 new net::IOBufferWithSize(body_length);
402 memcpy(body_buffer->data(), message->body.data(), message->body.length());
403 if (append_zero)
404 body_buffer->data()[body_length - 1] = 0;
405 outgoing_queue_.push(body_buffer);
406 if (zero_mask_ && (body_length & zero_mask_) == 0) {
407 // Send a zero length packet.
408 outgoing_queue_.push(new net::IOBufferWithSize(0));
411 ProcessOutgoing();
414 void AndroidUsbDevice::ProcessOutgoing() {
415 DCHECK(message_loop_ == base::MessageLoop::current());
417 if (outgoing_queue_.empty() || !usb_handle_.get())
418 return;
420 BulkMessage message = outgoing_queue_.front();
421 outgoing_queue_.pop();
422 DumpMessage(true, message->data(), message->size());
423 usb_handle_->BulkTransfer(device::USB_DIRECTION_OUTBOUND,
424 outbound_address_,
425 message.get(),
426 message->size(),
427 kUsbTimeout,
428 base::Bind(&AndroidUsbDevice::OutgoingMessageSent,
429 weak_factory_.GetWeakPtr()));
432 void AndroidUsbDevice::OutgoingMessageSent(UsbTransferStatus status,
433 scoped_refptr<net::IOBuffer> buffer,
434 size_t result) {
435 DCHECK(message_loop_ == base::MessageLoop::current());
437 if (status != device::USB_TRANSFER_COMPLETED)
438 return;
439 message_loop_->PostTask(FROM_HERE,
440 base::Bind(&AndroidUsbDevice::ProcessOutgoing, this));
443 void AndroidUsbDevice::ReadHeader() {
444 DCHECK(message_loop_ == base::MessageLoop::current());
446 if (!usb_handle_.get())
447 return;
448 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kHeaderSize);
449 usb_handle_->BulkTransfer(
450 device::USB_DIRECTION_INBOUND,
451 inbound_address_,
452 buffer.get(),
453 kHeaderSize,
454 kUsbTimeout,
455 base::Bind(&AndroidUsbDevice::ParseHeader, weak_factory_.GetWeakPtr()));
458 void AndroidUsbDevice::ParseHeader(UsbTransferStatus status,
459 scoped_refptr<net::IOBuffer> buffer,
460 size_t result) {
461 DCHECK(message_loop_ == base::MessageLoop::current());
463 if (status == device::USB_TRANSFER_TIMEOUT) {
464 message_loop_->PostTask(FROM_HERE,
465 base::Bind(&AndroidUsbDevice::ReadHeader, this));
466 return;
469 if (status != device::USB_TRANSFER_COMPLETED || result != kHeaderSize) {
470 TransferError(status);
471 return;
474 DumpMessage(false, buffer->data(), result);
475 std::vector<uint32> header(6);
476 memcpy(&header[0], buffer->data(), result);
477 scoped_ptr<AdbMessage> message(
478 new AdbMessage(header[0], header[1], header[2], ""));
479 uint32 data_length = header[3];
480 uint32 data_check = header[4];
481 uint32 magic = header[5];
482 if ((message->command ^ 0xffffffff) != magic) {
483 TransferError(device::USB_TRANSFER_ERROR);
484 return;
487 if (data_length == 0) {
488 message_loop_->PostTask(FROM_HERE,
489 base::Bind(&AndroidUsbDevice::HandleIncoming, this,
490 base::Passed(&message)));
491 return;
494 message_loop_->PostTask(FROM_HERE,
495 base::Bind(&AndroidUsbDevice::ReadBody, this,
496 base::Passed(&message), data_length, data_check));
499 void AndroidUsbDevice::ReadBody(scoped_ptr<AdbMessage> message,
500 uint32 data_length,
501 uint32 data_check) {
502 DCHECK(message_loop_ == base::MessageLoop::current());
504 if (!usb_handle_.get())
505 return;
506 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(data_length);
507 usb_handle_->BulkTransfer(device::USB_DIRECTION_INBOUND,
508 inbound_address_,
509 buffer.get(),
510 data_length,
511 kUsbTimeout,
512 base::Bind(&AndroidUsbDevice::ParseBody,
513 weak_factory_.GetWeakPtr(),
514 base::Passed(&message),
515 data_length,
516 data_check));
519 void AndroidUsbDevice::ParseBody(scoped_ptr<AdbMessage> message,
520 uint32 data_length,
521 uint32 data_check,
522 UsbTransferStatus status,
523 scoped_refptr<net::IOBuffer> buffer,
524 size_t result) {
525 DCHECK(message_loop_ == base::MessageLoop::current());
527 if (status == device::USB_TRANSFER_TIMEOUT) {
528 message_loop_->PostTask(FROM_HERE,
529 base::Bind(&AndroidUsbDevice::ReadBody, this,
530 base::Passed(&message), data_length, data_check));
531 return;
534 if (status != device::USB_TRANSFER_COMPLETED ||
535 static_cast<uint32>(result) != data_length) {
536 TransferError(status);
537 return;
540 DumpMessage(false, buffer->data(), data_length);
541 message->body = std::string(buffer->data(), result);
542 if (Checksum(message->body) != data_check) {
543 TransferError(device::USB_TRANSFER_ERROR);
544 return;
547 message_loop_->PostTask(FROM_HERE,
548 base::Bind(&AndroidUsbDevice::HandleIncoming, this,
549 base::Passed(&message)));
552 void AndroidUsbDevice::HandleIncoming(scoped_ptr<AdbMessage> message) {
553 DCHECK(message_loop_ == base::MessageLoop::current());
555 switch (message->command) {
556 case AdbMessage::kCommandAUTH:
558 DCHECK_EQ(message->arg0, static_cast<uint32>(AdbMessage::kAuthToken));
559 if (signature_sent_) {
560 Queue(make_scoped_ptr(new AdbMessage(
561 AdbMessage::kCommandAUTH,
562 AdbMessage::kAuthRSAPublicKey, 0,
563 AndroidRSAPublicKey(rsa_key_.get()))));
564 } else {
565 signature_sent_ = true;
566 std::string signature = AndroidRSASign(rsa_key_.get(), message->body);
567 if (!signature.empty()) {
568 Queue(make_scoped_ptr(new AdbMessage(AdbMessage::kCommandAUTH,
569 AdbMessage::kAuthSignature, 0,
570 signature)));
571 } else {
572 Queue(make_scoped_ptr(new AdbMessage(
573 AdbMessage::kCommandAUTH,
574 AdbMessage::kAuthRSAPublicKey, 0,
575 AndroidRSAPublicKey(rsa_key_.get()))));
579 break;
580 case AdbMessage::kCommandCNXN:
582 is_connected_ = true;
583 PendingMessages pending;
584 pending.swap(pending_messages_);
585 for (PendingMessages::iterator it = pending.begin();
586 it != pending.end(); ++it) {
587 Queue(make_scoped_ptr(*it));
590 break;
591 case AdbMessage::kCommandOKAY:
592 case AdbMessage::kCommandWRTE:
593 case AdbMessage::kCommandCLSE:
595 AndroidUsbSockets::iterator it = sockets_.find(message->arg1);
596 if (it != sockets_.end())
597 it->second->HandleIncoming(message.Pass());
599 break;
600 default:
601 break;
603 ReadHeader();
606 void AndroidUsbDevice::TransferError(UsbTransferStatus status) {
607 DCHECK(message_loop_ == base::MessageLoop::current());
609 message_loop_->PostTask(FROM_HERE,
610 base::Bind(&AndroidUsbDevice::Terminate, this));
613 void AndroidUsbDevice::TerminateIfReleased(
614 scoped_refptr<UsbDeviceHandle> usb_handle) {
615 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
616 if (usb_handle->GetDevice().get())
617 return;
618 message_loop_->PostTask(FROM_HERE,
619 base::Bind(&AndroidUsbDevice::Terminate, this));
622 void AndroidUsbDevice::Terminate() {
623 DCHECK(message_loop_ == base::MessageLoop::current());
625 std::vector<AndroidUsbDevice*>::iterator it =
626 std::find(g_devices.Get().begin(), g_devices.Get().end(), this);
627 if (it != g_devices.Get().end())
628 g_devices.Get().erase(it);
630 if (!usb_handle_.get())
631 return;
633 // Make sure we zero-out handle so that closing connections did not open
634 // new connections.
635 scoped_refptr<UsbDeviceHandle> usb_handle = usb_handle_;
636 usb_handle_ = NULL;
638 // Iterate over copy.
639 AndroidUsbSockets sockets(sockets_);
640 for (AndroidUsbSockets::iterator it = sockets.begin();
641 it != sockets.end(); ++it) {
642 it->second->Terminated(true);
644 DCHECK(sockets_.empty());
646 BrowserThread::PostTask(
647 BrowserThread::FILE, FROM_HERE,
648 base::Bind(&ReleaseInterface, usb_handle, interface_id_));
651 void AndroidUsbDevice::SocketDeleted(uint32 socket_id) {
652 DCHECK(message_loop_ == base::MessageLoop::current());
654 sockets_.erase(socket_id);