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.
4 
5 #include "services/device/usb/usb_device_handle_impl.h"
6 
7 #include <algorithm>
8 #include <memory>
9 #include <numeric>
10 #include <utility>
11 #include <vector>
12 
13 #include "base/bind.h"
14 #include "base/bind_helpers.h"
15 #include "base/location.h"
16 #include "base/macros.h"
17 #include "base/memory/ref_counted_memory.h"
18 #include "base/sequence_checker.h"
19 #include "base/single_thread_task_runner.h"
20 #include "base/stl_util.h"
21 #include "base/strings/string16.h"
22 #include "base/threading/scoped_blocking_call.h"
23 #include "base/threading/thread_task_runner_handle.h"
24 #include "components/device_event_log/device_event_log.h"
25 #include "services/device/public/cpp/usb/usb_utils.h"
26 #include "services/device/usb/usb_context.h"
27 #include "services/device/usb/usb_descriptors.h"
28 #include "services/device/usb/usb_device_impl.h"
29 #include "services/device/usb/usb_error.h"
30 #include "services/device/usb/usb_service.h"
31 #include "third_party/libusb/src/libusb/libusb.h"
32 
33 namespace device {
34 
35 using mojom::UsbControlTransferRecipient;
36 using mojom::UsbControlTransferType;
37 using mojom::UsbIsochronousPacketPtr;
38 using mojom::UsbTransferDirection;
39 using mojom::UsbTransferStatus;
40 using mojom::UsbTransferType;
41 
42 void HandleTransferCompletion(PlatformUsbTransferHandle transfer);
43 
44 namespace {
45 
ConvertTransferDirection(UsbTransferDirection direction)46 uint8_t ConvertTransferDirection(UsbTransferDirection direction) {
47   switch (direction) {
48     case UsbTransferDirection::INBOUND:
49       return LIBUSB_ENDPOINT_IN;
50     case UsbTransferDirection::OUTBOUND:
51       return LIBUSB_ENDPOINT_OUT;
52   }
53   NOTREACHED();
54   return 0;
55 }
56 
CreateRequestType(UsbTransferDirection direction,UsbControlTransferType request_type,UsbControlTransferRecipient recipient)57 uint8_t CreateRequestType(UsbTransferDirection direction,
58                           UsbControlTransferType request_type,
59                           UsbControlTransferRecipient recipient) {
60   uint8_t result = ConvertTransferDirection(direction);
61 
62   switch (request_type) {
63     case UsbControlTransferType::STANDARD:
64       result |= LIBUSB_REQUEST_TYPE_STANDARD;
65       break;
66     case UsbControlTransferType::CLASS:
67       result |= LIBUSB_REQUEST_TYPE_CLASS;
68       break;
69     case UsbControlTransferType::VENDOR:
70       result |= LIBUSB_REQUEST_TYPE_VENDOR;
71       break;
72     case UsbControlTransferType::RESERVED:
73       result |= LIBUSB_REQUEST_TYPE_RESERVED;
74       break;
75   }
76 
77   switch (recipient) {
78     case UsbControlTransferRecipient::DEVICE:
79       result |= LIBUSB_RECIPIENT_DEVICE;
80       break;
81     case UsbControlTransferRecipient::INTERFACE:
82       result |= LIBUSB_RECIPIENT_INTERFACE;
83       break;
84     case UsbControlTransferRecipient::ENDPOINT:
85       result |= LIBUSB_RECIPIENT_ENDPOINT;
86       break;
87     case UsbControlTransferRecipient::OTHER:
88       result |= LIBUSB_RECIPIENT_OTHER;
89       break;
90   }
91 
92   return result;
93 }
94 
ConvertTransferStatus(const libusb_transfer_status status)95 static UsbTransferStatus ConvertTransferStatus(
96     const libusb_transfer_status status) {
97   switch (status) {
98     case LIBUSB_TRANSFER_COMPLETED:
99       return UsbTransferStatus::COMPLETED;
100     case LIBUSB_TRANSFER_ERROR:
101       return UsbTransferStatus::TRANSFER_ERROR;
102     case LIBUSB_TRANSFER_TIMED_OUT:
103       return UsbTransferStatus::TIMEOUT;
104     case LIBUSB_TRANSFER_STALL:
105       return UsbTransferStatus::STALLED;
106     case LIBUSB_TRANSFER_NO_DEVICE:
107       return UsbTransferStatus::DISCONNECT;
108     case LIBUSB_TRANSFER_OVERFLOW:
109       return UsbTransferStatus::BABBLE;
110     case LIBUSB_TRANSFER_CANCELLED:
111       return UsbTransferStatus::CANCELLED;
112   }
113   NOTREACHED();
114   return UsbTransferStatus::TRANSFER_ERROR;
115 }
116 
117 }  // namespace
118 
119 class UsbDeviceHandleImpl::InterfaceClaimer
120     : public base::RefCountedThreadSafe<UsbDeviceHandleImpl::InterfaceClaimer> {
121  public:
122   InterfaceClaimer(scoped_refptr<UsbDeviceHandleImpl> handle,
123                    int interface_number,
124                    scoped_refptr<base::SequencedTaskRunner> task_runner);
125 
interface_number() const126   int interface_number() const { return interface_number_; }
alternate_setting() const127   int alternate_setting() const { return alternate_setting_; }
set_alternate_setting(const int alternate_setting)128   void set_alternate_setting(const int alternate_setting) {
129     alternate_setting_ = alternate_setting;
130   }
131 
set_release_callback(ResultCallback callback)132   void set_release_callback(ResultCallback callback) {
133     release_callback_ = std::move(callback);
134   }
135 
136  private:
137   friend class base::RefCountedThreadSafe<InterfaceClaimer>;
138   ~InterfaceClaimer();
139 
140   const scoped_refptr<UsbDeviceHandleImpl> handle_;
141   const int interface_number_;
142   int alternate_setting_;
143   const scoped_refptr<base::SequencedTaskRunner> task_runner_;
144   ResultCallback release_callback_;
145   base::SequenceChecker sequence_checker_;
146 
147   DISALLOW_COPY_AND_ASSIGN(InterfaceClaimer);
148 };
149 
InterfaceClaimer(scoped_refptr<UsbDeviceHandleImpl> handle,int interface_number,scoped_refptr<base::SequencedTaskRunner> task_runner)150 UsbDeviceHandleImpl::InterfaceClaimer::InterfaceClaimer(
151     scoped_refptr<UsbDeviceHandleImpl> handle,
152     int interface_number,
153     scoped_refptr<base::SequencedTaskRunner> task_runner)
154     : handle_(handle),
155       interface_number_(interface_number),
156       alternate_setting_(0),
157       task_runner_(task_runner) {}
158 
~InterfaceClaimer()159 UsbDeviceHandleImpl::InterfaceClaimer::~InterfaceClaimer() {
160   DCHECK(sequence_checker_.CalledOnValidSequence());
161   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
162                                                 base::BlockingType::MAY_BLOCK);
163   int rc = libusb_release_interface(handle_->handle(), interface_number_);
164   if (rc != LIBUSB_SUCCESS) {
165     USB_LOG(DEBUG) << "Failed to release interface: "
166                    << ConvertPlatformUsbErrorToString(rc);
167   }
168   if (!release_callback_.is_null()) {
169     task_runner_->PostTask(
170         FROM_HERE,
171         base::BindOnce(std::move(release_callback_), rc == LIBUSB_SUCCESS));
172   }
173 }
174 
175 // This inner class owns the underlying libusb_transfer and may outlast
176 // the UsbDeviceHandle that created it.
177 class UsbDeviceHandleImpl::Transfer {
178  public:
179   // These functions takes |*callback| if they successfully create Transfer
180   // instance, otherwise |*callback| left unchanged.
181   static std::unique_ptr<Transfer> CreateControlTransfer(
182       scoped_refptr<UsbDeviceHandleImpl> device_handle,
183       uint8_t type,
184       uint8_t request,
185       uint16_t value,
186       uint16_t index,
187       uint16_t length,
188       scoped_refptr<base::RefCountedBytes> buffer,
189       unsigned int timeout,
190       TransferCallback* callback);
191   static std::unique_ptr<Transfer> CreateBulkTransfer(
192       scoped_refptr<UsbDeviceHandleImpl> device_handle,
193       uint8_t endpoint,
194       scoped_refptr<base::RefCountedBytes> buffer,
195       int length,
196       unsigned int timeout,
197       TransferCallback* callback);
198   static std::unique_ptr<Transfer> CreateInterruptTransfer(
199       scoped_refptr<UsbDeviceHandleImpl> device_handle,
200       uint8_t endpoint,
201       scoped_refptr<base::RefCountedBytes> buffer,
202       int length,
203       unsigned int timeout,
204       TransferCallback* callback);
205   static std::unique_ptr<Transfer> CreateIsochronousTransfer(
206       scoped_refptr<UsbDeviceHandleImpl> device_handle,
207       uint8_t endpoint,
208       scoped_refptr<base::RefCountedBytes> buffer,
209       size_t length,
210       const std::vector<uint32_t>& packet_lengths,
211       unsigned int timeout,
212       IsochronousTransferCallback* callback);
213 
214   ~Transfer();
215 
216   void Submit();
217   void Cancel();
218   void ProcessCompletion();
219   void TransferComplete(UsbTransferStatus status, size_t bytes_transferred);
220 
claimed_interface() const221   const UsbDeviceHandleImpl::InterfaceClaimer* claimed_interface() const {
222     return claimed_interface_.get();
223   }
224 
225  private:
226   Transfer(scoped_refptr<UsbDeviceHandleImpl> device_handle,
227            scoped_refptr<InterfaceClaimer> claimed_interface,
228            UsbTransferType transfer_type,
229            scoped_refptr<base::RefCountedBytes> buffer,
230            size_t length,
231            TransferCallback callback);
232   Transfer(scoped_refptr<UsbDeviceHandleImpl> device_handle,
233            scoped_refptr<InterfaceClaimer> claimed_interface,
234            scoped_refptr<base::RefCountedBytes> buffer,
235            IsochronousTransferCallback callback);
236 
237   static void LIBUSB_CALL PlatformCallback(PlatformUsbTransferHandle handle);
238 
239   void IsochronousTransferComplete();
240 
241   UsbTransferType transfer_type_;
242   scoped_refptr<UsbDeviceHandleImpl> device_handle_;
243   PlatformUsbTransferHandle platform_transfer_ = nullptr;
244   scoped_refptr<base::RefCountedBytes> buffer_;
245   scoped_refptr<UsbDeviceHandleImpl::InterfaceClaimer> claimed_interface_;
246   size_t length_;
247   bool cancelled_ = false;
248   TransferCallback callback_;
249   IsochronousTransferCallback iso_callback_;
250   scoped_refptr<base::SequencedTaskRunner> task_runner_;
251 };
252 
253 // static
254 std::unique_ptr<UsbDeviceHandleImpl::Transfer>
CreateControlTransfer(scoped_refptr<UsbDeviceHandleImpl> device_handle,uint8_t type,uint8_t request,uint16_t value,uint16_t index,uint16_t length,scoped_refptr<base::RefCountedBytes> buffer,unsigned int timeout,TransferCallback * callback)255 UsbDeviceHandleImpl::Transfer::CreateControlTransfer(
256     scoped_refptr<UsbDeviceHandleImpl> device_handle,
257     uint8_t type,
258     uint8_t request,
259     uint16_t value,
260     uint16_t index,
261     uint16_t length,
262     scoped_refptr<base::RefCountedBytes> buffer,
263     unsigned int timeout,
264     TransferCallback* callback) {
265   std::unique_ptr<Transfer> transfer(
266       new Transfer(device_handle, nullptr, UsbTransferType::CONTROL, buffer,
267                    length + LIBUSB_CONTROL_SETUP_SIZE, std::move(*callback)));
268 
269   transfer->platform_transfer_ = libusb_alloc_transfer(0);
270   if (!transfer->platform_transfer_) {
271     USB_LOG(ERROR) << "Failed to allocate control transfer.";
272     *callback = std::move(transfer->callback_);
273     return nullptr;
274   }
275 
276   libusb_fill_control_setup(buffer->front(), type, request, value, index,
277                             length);
278   libusb_fill_control_transfer(transfer->platform_transfer_,
279                                device_handle->handle(), buffer->front(),
280                                &UsbDeviceHandleImpl::Transfer::PlatformCallback,
281                                transfer.get(), timeout);
282 
283   return transfer;
284 }
285 
286 // static
287 std::unique_ptr<UsbDeviceHandleImpl::Transfer>
CreateBulkTransfer(scoped_refptr<UsbDeviceHandleImpl> device_handle,uint8_t endpoint,scoped_refptr<base::RefCountedBytes> buffer,int length,unsigned int timeout,TransferCallback * callback)288 UsbDeviceHandleImpl::Transfer::CreateBulkTransfer(
289     scoped_refptr<UsbDeviceHandleImpl> device_handle,
290     uint8_t endpoint,
291     scoped_refptr<base::RefCountedBytes> buffer,
292     int length,
293     unsigned int timeout,
294     TransferCallback* callback) {
295   std::unique_ptr<Transfer> transfer(new Transfer(
296       device_handle, device_handle->GetClaimedInterfaceForEndpoint(endpoint),
297       UsbTransferType::BULK, buffer, length, std::move(*callback)));
298 
299   transfer->platform_transfer_ = libusb_alloc_transfer(0);
300   if (!transfer->platform_transfer_) {
301     USB_LOG(ERROR) << "Failed to allocate bulk transfer.";
302     *callback = std::move(transfer->callback_);
303     return nullptr;
304   }
305 
306   libusb_fill_bulk_transfer(
307       transfer->platform_transfer_, device_handle->handle(), endpoint,
308       buffer->front(), length, &UsbDeviceHandleImpl::Transfer::PlatformCallback,
309       transfer.get(), timeout);
310 
311   return transfer;
312 }
313 
314 // static
315 std::unique_ptr<UsbDeviceHandleImpl::Transfer>
CreateInterruptTransfer(scoped_refptr<UsbDeviceHandleImpl> device_handle,uint8_t endpoint,scoped_refptr<base::RefCountedBytes> buffer,int length,unsigned int timeout,TransferCallback * callback)316 UsbDeviceHandleImpl::Transfer::CreateInterruptTransfer(
317     scoped_refptr<UsbDeviceHandleImpl> device_handle,
318     uint8_t endpoint,
319     scoped_refptr<base::RefCountedBytes> buffer,
320     int length,
321     unsigned int timeout,
322     TransferCallback* callback) {
323   std::unique_ptr<Transfer> transfer(new Transfer(
324       device_handle, device_handle->GetClaimedInterfaceForEndpoint(endpoint),
325       UsbTransferType::INTERRUPT, buffer, length, std::move(*callback)));
326 
327   transfer->platform_transfer_ = libusb_alloc_transfer(0);
328   if (!transfer->platform_transfer_) {
329     USB_LOG(ERROR) << "Failed to allocate interrupt transfer.";
330     *callback = std::move(transfer->callback_);
331     return nullptr;
332   }
333 
334   libusb_fill_interrupt_transfer(
335       transfer->platform_transfer_, device_handle->handle(), endpoint,
336       buffer->front(), length, &UsbDeviceHandleImpl::Transfer::PlatformCallback,
337       transfer.get(), timeout);
338 
339   return transfer;
340 }
341 
342 // static
343 std::unique_ptr<UsbDeviceHandleImpl::Transfer>
CreateIsochronousTransfer(scoped_refptr<UsbDeviceHandleImpl> device_handle,uint8_t endpoint,scoped_refptr<base::RefCountedBytes> buffer,size_t length,const std::vector<uint32_t> & packet_lengths,unsigned int timeout,IsochronousTransferCallback * callback)344 UsbDeviceHandleImpl::Transfer::CreateIsochronousTransfer(
345     scoped_refptr<UsbDeviceHandleImpl> device_handle,
346     uint8_t endpoint,
347     scoped_refptr<base::RefCountedBytes> buffer,
348     size_t length,
349     const std::vector<uint32_t>& packet_lengths,
350     unsigned int timeout,
351     IsochronousTransferCallback* callback) {
352   std::unique_ptr<Transfer> transfer(new Transfer(
353       device_handle, device_handle->GetClaimedInterfaceForEndpoint(endpoint),
354       buffer, std::move(*callback)));
355 
356   int num_packets = static_cast<int>(packet_lengths.size());
357   transfer->platform_transfer_ = libusb_alloc_transfer(num_packets);
358   if (!transfer->platform_transfer_) {
359     USB_LOG(ERROR) << "Failed to allocate isochronous transfer.";
360     *callback = std::move(transfer->iso_callback_);
361     return nullptr;
362   }
363 
364   libusb_fill_iso_transfer(
365       transfer->platform_transfer_, device_handle->handle(), endpoint,
366       buffer->front(), static_cast<int>(length), num_packets,
367       &Transfer::PlatformCallback, transfer.get(), timeout);
368 
369   for (size_t i = 0; i < packet_lengths.size(); ++i)
370     transfer->platform_transfer_->iso_packet_desc[i].length = packet_lengths[i];
371 
372   return transfer;
373 }
374 
Transfer(scoped_refptr<UsbDeviceHandleImpl> device_handle,scoped_refptr<InterfaceClaimer> claimed_interface,UsbTransferType transfer_type,scoped_refptr<base::RefCountedBytes> buffer,size_t length,TransferCallback callback)375 UsbDeviceHandleImpl::Transfer::Transfer(
376     scoped_refptr<UsbDeviceHandleImpl> device_handle,
377     scoped_refptr<InterfaceClaimer> claimed_interface,
378     UsbTransferType transfer_type,
379     scoped_refptr<base::RefCountedBytes> buffer,
380     size_t length,
381     TransferCallback callback)
382     : transfer_type_(transfer_type),
383       device_handle_(device_handle),
384       buffer_(buffer),
385       claimed_interface_(claimed_interface),
386       length_(length),
387       callback_(std::move(callback)),
388       task_runner_(base::SequencedTaskRunnerHandle::Get()) {}
389 
Transfer(scoped_refptr<UsbDeviceHandleImpl> device_handle,scoped_refptr<InterfaceClaimer> claimed_interface,scoped_refptr<base::RefCountedBytes> buffer,IsochronousTransferCallback callback)390 UsbDeviceHandleImpl::Transfer::Transfer(
391     scoped_refptr<UsbDeviceHandleImpl> device_handle,
392     scoped_refptr<InterfaceClaimer> claimed_interface,
393     scoped_refptr<base::RefCountedBytes> buffer,
394     IsochronousTransferCallback callback)
395     : transfer_type_(UsbTransferType::ISOCHRONOUS),
396       device_handle_(device_handle),
397       buffer_(buffer),
398       claimed_interface_(claimed_interface),
399       iso_callback_(std::move(callback)),
400       task_runner_(base::SequencedTaskRunnerHandle::Get()) {}
401 
~Transfer()402 UsbDeviceHandleImpl::Transfer::~Transfer() {
403   if (platform_transfer_) {
404     libusb_free_transfer(platform_transfer_);
405   }
406 }
407 
Submit()408 void UsbDeviceHandleImpl::Transfer::Submit() {
409   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
410                                                 base::BlockingType::MAY_BLOCK);
411   const int rv = libusb_submit_transfer(platform_transfer_);
412   if (rv != LIBUSB_SUCCESS) {
413     USB_LOG(EVENT) << "Failed to submit transfer: "
414                    << ConvertPlatformUsbErrorToString(rv);
415     TransferComplete(UsbTransferStatus::TRANSFER_ERROR, 0);
416   }
417 }
418 
Cancel()419 void UsbDeviceHandleImpl::Transfer::Cancel() {
420   if (!cancelled_) {
421     libusb_cancel_transfer(platform_transfer_);
422     claimed_interface_ = nullptr;
423   }
424   cancelled_ = true;
425 }
426 
ProcessCompletion()427 void UsbDeviceHandleImpl::Transfer::ProcessCompletion() {
428   DCHECK_GE(platform_transfer_->actual_length, 0)
429       << "Negative actual length received";
430   size_t actual_length =
431       static_cast<size_t>(std::max(platform_transfer_->actual_length, 0));
432 
433   DCHECK(length_ >= actual_length)
434       << "data too big for our buffer (libusb failure?)";
435 
436   switch (transfer_type_) {
437     case UsbTransferType::CONTROL:
438       // If the transfer is a control transfer we do not expose the control
439       // setup header to the caller. This logic strips off the header if
440       // present before invoking the callback provided with the transfer.
441       if (actual_length > 0) {
442         CHECK(length_ >= LIBUSB_CONTROL_SETUP_SIZE)
443             << "buffer was not correctly set: too small for the control header";
444 
445         if (length_ >= (LIBUSB_CONTROL_SETUP_SIZE + actual_length)) {
446           auto resized_buffer =
447               base::MakeRefCounted<base::RefCountedBytes>(actual_length);
448           memcpy(resized_buffer->front(),
449                  buffer_->front() + LIBUSB_CONTROL_SETUP_SIZE, actual_length);
450           buffer_ = resized_buffer;
451         }
452       }
453       FALLTHROUGH;
454 
455     case UsbTransferType::BULK:
456     case UsbTransferType::INTERRUPT:
457       TransferComplete(ConvertTransferStatus(platform_transfer_->status),
458                        actual_length);
459       break;
460 
461     case UsbTransferType::ISOCHRONOUS:
462       IsochronousTransferComplete();
463       break;
464 
465     default:
466       NOTREACHED() << "Invalid usb transfer type";
467       break;
468   }
469 }
470 
471 /* static */
PlatformCallback(PlatformUsbTransferHandle platform_transfer)472 void LIBUSB_CALL UsbDeviceHandleImpl::Transfer::PlatformCallback(
473     PlatformUsbTransferHandle platform_transfer) {
474   Transfer* transfer =
475       reinterpret_cast<Transfer*>(platform_transfer->user_data);
476   DCHECK(transfer->platform_transfer_ == platform_transfer);
477   transfer->ProcessCompletion();
478 }
479 
TransferComplete(UsbTransferStatus status,size_t bytes_transferred)480 void UsbDeviceHandleImpl::Transfer::TransferComplete(UsbTransferStatus status,
481                                                      size_t bytes_transferred) {
482   base::OnceClosure closure;
483   if (transfer_type_ == UsbTransferType::ISOCHRONOUS) {
484     DCHECK_NE(LIBUSB_TRANSFER_COMPLETED, platform_transfer_->status);
485     std::vector<UsbIsochronousPacketPtr> packets(
486         platform_transfer_->num_iso_packets);
487     for (size_t i = 0; i < packets.size(); ++i) {
488       packets[i] = mojom::UsbIsochronousPacket::New();
489       packets[i]->length = platform_transfer_->iso_packet_desc[i].length;
490       packets[i]->transferred_length = 0;
491       packets[i]->status = status;
492     }
493     closure =
494         base::BindOnce(std::move(iso_callback_), buffer_, std::move(packets));
495   } else {
496     closure = base::BindOnce(std::move(callback_), status, buffer_,
497                              bytes_transferred);
498   }
499   task_runner_->PostTask(
500       FROM_HERE,
501       base::BindOnce(&UsbDeviceHandleImpl::TransferComplete, device_handle_,
502                      base::Unretained(this), std::move(closure)));
503 }
504 
IsochronousTransferComplete()505 void UsbDeviceHandleImpl::Transfer::IsochronousTransferComplete() {
506   std::vector<UsbIsochronousPacketPtr> packets(
507       platform_transfer_->num_iso_packets);
508   for (size_t i = 0; i < packets.size(); ++i) {
509     packets[i] = mojom::UsbIsochronousPacket::New();
510     packets[i]->length = platform_transfer_->iso_packet_desc[i].length;
511     packets[i]->transferred_length =
512         platform_transfer_->iso_packet_desc[i].actual_length;
513     packets[i]->status =
514         ConvertTransferStatus(platform_transfer_->iso_packet_desc[i].status);
515   }
516   task_runner_->PostTask(
517       FROM_HERE, base::BindOnce(&UsbDeviceHandleImpl::TransferComplete,
518                                 device_handle_, base::Unretained(this),
519                                 base::BindOnce(std::move(iso_callback_),
520                                                buffer_, std::move(packets))));
521 }
522 
GetDevice() const523 scoped_refptr<UsbDevice> UsbDeviceHandleImpl::GetDevice() const {
524   return device_;
525 }
526 
Close()527 void UsbDeviceHandleImpl::Close() {
528   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
529 
530   if (!device_)
531     return;
532 
533   // Cancel all the transfers, their callbacks will be called some time later.
534   for (Transfer* transfer : transfers_)
535     transfer->Cancel();
536 
537   // Release all remaining interfaces once their transfers have completed.
538   // This loop must ensure that what may be the final reference is released on
539   // the right thread.
540   for (auto& map_entry : claimed_interfaces_) {
541     blocking_task_runner_->ReleaseSoon(FROM_HERE, std::move(map_entry.second));
542   }
543 
544   device_->HandleClosed(this);
545   device_ = nullptr;
546 
547   // The device handle cannot be closed here. When libusb_cancel_transfer is
548   // finished the last references to this device will be released and the
549   // destructor will close the handle.
550 }
551 
SetConfiguration(int configuration_value,ResultCallback callback)552 void UsbDeviceHandleImpl::SetConfiguration(int configuration_value,
553                                            ResultCallback callback) {
554   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
555 
556   if (!device_) {
557     std::move(callback).Run(false);
558     return;
559   }
560 
561   for (Transfer* transfer : transfers_) {
562     transfer->Cancel();
563   }
564   claimed_interfaces_.clear();
565 
566   blocking_task_runner_->PostTask(
567       FROM_HERE,
568       base::BindOnce(&UsbDeviceHandleImpl::SetConfigurationBlocking, this,
569                      configuration_value, std::move(callback)));
570 }
571 
ClaimInterface(int interface_number,ResultCallback callback)572 void UsbDeviceHandleImpl::ClaimInterface(int interface_number,
573                                          ResultCallback callback) {
574   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
575 
576   if (!device_) {
577     std::move(callback).Run(false);
578     return;
579   }
580   if (base::Contains(claimed_interfaces_, interface_number)) {
581     std::move(callback).Run(true);
582     return;
583   }
584 
585   blocking_task_runner_->PostTask(
586       FROM_HERE, base::BindOnce(&UsbDeviceHandleImpl::ClaimInterfaceBlocking,
587                                 this, interface_number, std::move(callback)));
588 }
589 
ReleaseInterface(int interface_number,ResultCallback callback)590 void UsbDeviceHandleImpl::ReleaseInterface(int interface_number,
591                                            ResultCallback callback) {
592   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
593 
594   if (!device_ || !base::Contains(claimed_interfaces_, interface_number)) {
595     task_runner_->PostTask(FROM_HERE,
596                            base::BindOnce(std::move(callback), false));
597     return;
598   }
599 
600   // Cancel all the transfers on that interface.
601   InterfaceClaimer* interface_claimer =
602       claimed_interfaces_[interface_number].get();
603   for (Transfer* transfer : transfers_) {
604     if (transfer->claimed_interface() == interface_claimer) {
605       transfer->Cancel();
606     }
607   }
608   interface_claimer->set_release_callback(std::move(callback));
609   blocking_task_runner_->ReleaseSoon(
610       FROM_HERE, std::move(claimed_interfaces_[interface_number]));
611   claimed_interfaces_.erase(interface_number);
612 
613   RefreshEndpointMap();
614 }
615 
SetInterfaceAlternateSetting(int interface_number,int alternate_setting,ResultCallback callback)616 void UsbDeviceHandleImpl::SetInterfaceAlternateSetting(
617     int interface_number,
618     int alternate_setting,
619     ResultCallback callback) {
620   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
621 
622   if (!device_ || !base::Contains(claimed_interfaces_, interface_number)) {
623     std::move(callback).Run(false);
624     return;
625   }
626 
627   blocking_task_runner_->PostTask(
628       FROM_HERE,
629       base::BindOnce(&UsbDeviceHandleImpl::SetInterfaceAlternateSettingBlocking,
630                      this, interface_number, alternate_setting,
631                      std::move(callback)));
632 }
633 
ResetDevice(ResultCallback callback)634 void UsbDeviceHandleImpl::ResetDevice(ResultCallback callback) {
635   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
636 
637   if (!device_) {
638     std::move(callback).Run(false);
639     return;
640   }
641 
642   blocking_task_runner_->PostTask(
643       FROM_HERE, base::BindOnce(&UsbDeviceHandleImpl::ResetDeviceBlocking, this,
644                                 std::move(callback)));
645 }
646 
ClearHalt(uint8_t endpoint,ResultCallback callback)647 void UsbDeviceHandleImpl::ClearHalt(uint8_t endpoint, ResultCallback callback) {
648   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
649 
650   if (!device_) {
651     std::move(callback).Run(false);
652     return;
653   }
654 
655   InterfaceClaimer* interface_claimer =
656       GetClaimedInterfaceForEndpoint(endpoint).get();
657   for (Transfer* transfer : transfers_) {
658     if (transfer->claimed_interface() == interface_claimer) {
659       transfer->Cancel();
660     }
661   }
662 
663   blocking_task_runner_->PostTask(
664       FROM_HERE, base::BindOnce(&UsbDeviceHandleImpl::ClearHaltBlocking, this,
665                                 endpoint, std::move(callback)));
666 }
667 
ControlTransfer(UsbTransferDirection direction,UsbControlTransferType request_type,UsbControlTransferRecipient recipient,uint8_t request,uint16_t value,uint16_t index,scoped_refptr<base::RefCountedBytes> buffer,unsigned int timeout,TransferCallback callback)668 void UsbDeviceHandleImpl::ControlTransfer(
669     UsbTransferDirection direction,
670     UsbControlTransferType request_type,
671     UsbControlTransferRecipient recipient,
672     uint8_t request,
673     uint16_t value,
674     uint16_t index,
675     scoped_refptr<base::RefCountedBytes> buffer,
676     unsigned int timeout,
677     TransferCallback callback) {
678   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
679 
680   if (!device_) {
681     task_runner_->PostTask(
682         FROM_HERE, base::BindOnce(std::move(callback),
683                                   UsbTransferStatus::DISCONNECT, buffer, 0));
684     return;
685   }
686 
687   if (!base::IsValueInRangeForNumericType<uint16_t>(buffer->size())) {
688     USB_LOG(USER) << "Transfer too long.";
689     task_runner_->PostTask(
690         FROM_HERE,
691         base::BindOnce(std::move(callback), UsbTransferStatus::TRANSFER_ERROR,
692                        buffer, 0));
693     return;
694   }
695 
696   const size_t resized_length = LIBUSB_CONTROL_SETUP_SIZE + buffer->size();
697   auto resized_buffer =
698       base::MakeRefCounted<base::RefCountedBytes>(resized_length);
699   memcpy(resized_buffer->front() + LIBUSB_CONTROL_SETUP_SIZE, buffer->front(),
700          buffer->size());
701 
702   std::unique_ptr<Transfer> transfer = Transfer::CreateControlTransfer(
703       this, CreateRequestType(direction, request_type, recipient), request,
704       value, index, static_cast<uint16_t>(buffer->size()), resized_buffer,
705       timeout, &callback);
706   if (!transfer) {
707     DCHECK(callback);
708     task_runner_->PostTask(
709         FROM_HERE,
710         base::BindOnce(std::move(callback), UsbTransferStatus::TRANSFER_ERROR,
711                        buffer, 0));
712     return;
713   }
714 
715   SubmitTransfer(std::move(transfer));
716 }
717 
IsochronousTransferIn(uint8_t endpoint_number,const std::vector<uint32_t> & packet_lengths,unsigned int timeout,IsochronousTransferCallback callback)718 void UsbDeviceHandleImpl::IsochronousTransferIn(
719     uint8_t endpoint_number,
720     const std::vector<uint32_t>& packet_lengths,
721     unsigned int timeout,
722     IsochronousTransferCallback callback) {
723   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
724 
725   if (!device_) {
726     ReportIsochronousTransferError(std::move(callback), packet_lengths,
727                                    UsbTransferStatus::DISCONNECT);
728     return;
729   }
730 
731   uint8_t endpoint_address =
732       ConvertTransferDirection(UsbTransferDirection::INBOUND) | endpoint_number;
733   size_t length =
734       std::accumulate(packet_lengths.begin(), packet_lengths.end(), 0u);
735   auto buffer = base::MakeRefCounted<base::RefCountedBytes>(length);
736   std::unique_ptr<Transfer> transfer = Transfer::CreateIsochronousTransfer(
737       this, endpoint_address, buffer, length, packet_lengths, timeout,
738       &callback);
739   DCHECK(transfer);
740   SubmitTransfer(std::move(transfer));
741 }
742 
IsochronousTransferOut(uint8_t endpoint_number,scoped_refptr<base::RefCountedBytes> buffer,const std::vector<uint32_t> & packet_lengths,unsigned int timeout,IsochronousTransferCallback callback)743 void UsbDeviceHandleImpl::IsochronousTransferOut(
744     uint8_t endpoint_number,
745     scoped_refptr<base::RefCountedBytes> buffer,
746     const std::vector<uint32_t>& packet_lengths,
747     unsigned int timeout,
748     IsochronousTransferCallback callback) {
749   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
750 
751   if (!device_) {
752     ReportIsochronousTransferError(std::move(callback), packet_lengths,
753                                    UsbTransferStatus::DISCONNECT);
754     return;
755   }
756 
757   uint8_t endpoint_address =
758       ConvertTransferDirection(UsbTransferDirection::OUTBOUND) |
759       endpoint_number;
760   size_t length =
761       std::accumulate(packet_lengths.begin(), packet_lengths.end(), 0u);
762   std::unique_ptr<Transfer> transfer = Transfer::CreateIsochronousTransfer(
763       this, endpoint_address, buffer, length, packet_lengths, timeout,
764       &callback);
765   DCHECK(transfer);
766   SubmitTransfer(std::move(transfer));
767 }
768 
GenericTransfer(UsbTransferDirection direction,uint8_t endpoint_number,scoped_refptr<base::RefCountedBytes> buffer,unsigned int timeout,TransferCallback callback)769 void UsbDeviceHandleImpl::GenericTransfer(
770     UsbTransferDirection direction,
771     uint8_t endpoint_number,
772     scoped_refptr<base::RefCountedBytes> buffer,
773     unsigned int timeout,
774     TransferCallback callback) {
775   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
776 
777   if (!device_) {
778     task_runner_->PostTask(
779         FROM_HERE, base::BindOnce(std::move(callback),
780                                   UsbTransferStatus::DISCONNECT, buffer, 0));
781     return;
782   }
783 
784   uint8_t endpoint_address =
785       ConvertTransferDirection(direction) | endpoint_number;
786   const auto endpoint_it = endpoint_map_.find(endpoint_address);
787   if (endpoint_it == endpoint_map_.end()) {
788     USB_LOG(DEBUG) << "Failed to submit transfer because endpoint "
789                    << static_cast<int>(endpoint_address)
790                    << " not part of a claimed interface.";
791     task_runner_->PostTask(
792         FROM_HERE,
793         base::BindOnce(std::move(callback), UsbTransferStatus::TRANSFER_ERROR,
794                        buffer, 0));
795     return;
796   }
797 
798   if (!base::IsValueInRangeForNumericType<int>(buffer->size())) {
799     USB_LOG(DEBUG) << "Transfer too long.";
800     task_runner_->PostTask(
801         FROM_HERE,
802         base::BindOnce(std::move(callback), UsbTransferStatus::TRANSFER_ERROR,
803                        buffer, 0));
804     return;
805   }
806 
807   std::unique_ptr<Transfer> transfer;
808   UsbTransferType transfer_type = endpoint_it->second.endpoint->type;
809   if (transfer_type == UsbTransferType::BULK) {
810     transfer = Transfer::CreateBulkTransfer(this, endpoint_address, buffer,
811                                             static_cast<int>(buffer->size()),
812                                             timeout, &callback);
813   } else if (transfer_type == UsbTransferType::INTERRUPT) {
814     transfer = Transfer::CreateInterruptTransfer(
815         this, endpoint_address, buffer, static_cast<int>(buffer->size()),
816         timeout, &callback);
817   } else {
818     USB_LOG(DEBUG) << "Endpoint " << static_cast<int>(endpoint_address)
819                    << " is not a bulk or interrupt endpoint.";
820     task_runner_->PostTask(
821         FROM_HERE,
822         base::BindOnce(std::move(callback), UsbTransferStatus::TRANSFER_ERROR,
823                        buffer, 0));
824     return;
825   }
826   DCHECK(transfer);
827   SubmitTransfer(std::move(transfer));
828 }
829 
FindInterfaceByEndpoint(uint8_t endpoint_address)830 const mojom::UsbInterfaceInfo* UsbDeviceHandleImpl::FindInterfaceByEndpoint(
831     uint8_t endpoint_address) {
832   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
833 
834   const auto endpoint_it = endpoint_map_.find(endpoint_address);
835   if (endpoint_it != endpoint_map_.end())
836     return endpoint_it->second.interface;
837   return nullptr;
838 }
839 
UsbDeviceHandleImpl(scoped_refptr<UsbDeviceImpl> device,ScopedLibusbDeviceHandle handle,scoped_refptr<base::SequencedTaskRunner> blocking_task_runner)840 UsbDeviceHandleImpl::UsbDeviceHandleImpl(
841     scoped_refptr<UsbDeviceImpl> device,
842     ScopedLibusbDeviceHandle handle,
843     scoped_refptr<base::SequencedTaskRunner> blocking_task_runner)
844     : device_(std::move(device)),
845       handle_(std::move(handle)),
846       task_runner_(base::SequencedTaskRunnerHandle::Get()),
847       blocking_task_runner_(blocking_task_runner) {
848   DCHECK(handle_.IsValid()) << "Cannot create device with an invalid handle.";
849 }
850 
~UsbDeviceHandleImpl()851 UsbDeviceHandleImpl::~UsbDeviceHandleImpl() {
852   DCHECK(!device_) << "UsbDeviceHandle must be closed before it is destroyed.";
853 
854   // This class is RefCountedThreadSafe and so the destructor may be called on
855   // any thread. libusb is not safe to reentrancy so be sure not to try to close
856   // the device from inside a transfer completion callback.
857   if (blocking_task_runner_->RunsTasksInCurrentSequence()) {
858     handle_.Reset();
859   } else {
860     blocking_task_runner_->PostTask(
861         FROM_HERE,
862         base::BindOnce(base::DoNothing::Once<ScopedLibusbDeviceHandle>(),
863                        std::move(handle_)));
864   }
865 }
866 
SetConfigurationBlocking(int configuration_value,ResultCallback callback)867 void UsbDeviceHandleImpl::SetConfigurationBlocking(int configuration_value,
868                                                    ResultCallback callback) {
869   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
870                                                 base::BlockingType::MAY_BLOCK);
871   int rv = libusb_set_configuration(handle(), configuration_value);
872   if (rv != LIBUSB_SUCCESS) {
873     USB_LOG(EVENT) << "Failed to set configuration " << configuration_value
874                    << ": " << ConvertPlatformUsbErrorToString(rv);
875   }
876   task_runner_->PostTask(
877       FROM_HERE,
878       base::BindOnce(&UsbDeviceHandleImpl::SetConfigurationComplete, this,
879                      rv == LIBUSB_SUCCESS, std::move(callback)));
880 }
881 
SetConfigurationComplete(bool success,ResultCallback callback)882 void UsbDeviceHandleImpl::SetConfigurationComplete(bool success,
883                                                    ResultCallback callback) {
884   if (!device_) {
885     std::move(callback).Run(false);
886     return;
887   }
888 
889   if (success) {
890     device_->RefreshActiveConfiguration();
891     RefreshEndpointMap();
892   }
893   std::move(callback).Run(success);
894 }
895 
ClaimInterfaceBlocking(int interface_number,ResultCallback callback)896 void UsbDeviceHandleImpl::ClaimInterfaceBlocking(int interface_number,
897                                                  ResultCallback callback) {
898   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
899                                                 base::BlockingType::MAY_BLOCK);
900   int rv = libusb_claim_interface(handle(), interface_number);
901   scoped_refptr<InterfaceClaimer> interface_claimer;
902   if (rv == LIBUSB_SUCCESS) {
903     interface_claimer =
904         new InterfaceClaimer(this, interface_number, task_runner_);
905   } else {
906     USB_LOG(EVENT) << "Failed to claim interface: "
907                    << ConvertPlatformUsbErrorToString(rv);
908   }
909   task_runner_->PostTask(
910       FROM_HERE, base::BindOnce(&UsbDeviceHandleImpl::ClaimInterfaceComplete,
911                                 this, interface_claimer, std::move(callback)));
912 }
913 
ClaimInterfaceComplete(scoped_refptr<InterfaceClaimer> interface_claimer,ResultCallback callback)914 void UsbDeviceHandleImpl::ClaimInterfaceComplete(
915     scoped_refptr<InterfaceClaimer> interface_claimer,
916     ResultCallback callback) {
917   if (!device_) {
918     if (interface_claimer) {
919       // Ensure that the InterfaceClaimer is released on the blocking thread.
920       blocking_task_runner_->ReleaseSoon(FROM_HERE,
921                                          std::move(interface_claimer));
922     }
923 
924     std::move(callback).Run(false);
925     return;
926   }
927 
928   if (interface_claimer) {
929     claimed_interfaces_[interface_claimer->interface_number()] =
930         interface_claimer;
931     RefreshEndpointMap();
932   }
933   std::move(callback).Run(interface_claimer != nullptr);
934 }
935 
SetInterfaceAlternateSettingBlocking(int interface_number,int alternate_setting,ResultCallback callback)936 void UsbDeviceHandleImpl::SetInterfaceAlternateSettingBlocking(
937     int interface_number,
938     int alternate_setting,
939     ResultCallback callback) {
940   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
941                                                 base::BlockingType::MAY_BLOCK);
942   int rv = libusb_set_interface_alt_setting(handle(), interface_number,
943                                             alternate_setting);
944   if (rv != LIBUSB_SUCCESS) {
945     USB_LOG(EVENT) << "Failed to set interface " << interface_number
946                    << " to alternate setting " << alternate_setting << ": "
947                    << ConvertPlatformUsbErrorToString(rv);
948   }
949   task_runner_->PostTask(
950       FROM_HERE,
951       base::BindOnce(&UsbDeviceHandleImpl::SetInterfaceAlternateSettingComplete,
952                      this, interface_number, alternate_setting,
953                      rv == LIBUSB_SUCCESS, std::move(callback)));
954 }
955 
SetInterfaceAlternateSettingComplete(int interface_number,int alternate_setting,bool success,ResultCallback callback)956 void UsbDeviceHandleImpl::SetInterfaceAlternateSettingComplete(
957     int interface_number,
958     int alternate_setting,
959     bool success,
960     ResultCallback callback) {
961   if (!device_) {
962     std::move(callback).Run(false);
963     return;
964   }
965 
966   if (success) {
967     claimed_interfaces_[interface_number]->set_alternate_setting(
968         alternate_setting);
969     RefreshEndpointMap();
970   }
971   std::move(callback).Run(success);
972 }
973 
ResetDeviceBlocking(ResultCallback callback)974 void UsbDeviceHandleImpl::ResetDeviceBlocking(ResultCallback callback) {
975   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
976                                                 base::BlockingType::MAY_BLOCK);
977   int rv = libusb_reset_device(handle());
978   if (rv != LIBUSB_SUCCESS) {
979     USB_LOG(EVENT) << "Failed to reset device: "
980                    << ConvertPlatformUsbErrorToString(rv);
981   }
982   task_runner_->PostTask(
983       FROM_HERE, base::BindOnce(std::move(callback), rv == LIBUSB_SUCCESS));
984 }
985 
ClearHaltBlocking(uint8_t endpoint,ResultCallback callback)986 void UsbDeviceHandleImpl::ClearHaltBlocking(uint8_t endpoint,
987                                             ResultCallback callback) {
988   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
989                                                 base::BlockingType::MAY_BLOCK);
990   int rv = libusb_clear_halt(handle(), endpoint);
991   if (rv != LIBUSB_SUCCESS) {
992     USB_LOG(EVENT) << "Failed to clear halt: "
993                    << ConvertPlatformUsbErrorToString(rv);
994   }
995   task_runner_->PostTask(
996       FROM_HERE, base::BindOnce(std::move(callback), rv == LIBUSB_SUCCESS));
997 }
998 
RefreshEndpointMap()999 void UsbDeviceHandleImpl::RefreshEndpointMap() {
1000   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
1001   DCHECK(device_);
1002   endpoint_map_.clear();
1003   const mojom::UsbConfigurationInfo* config = device_->GetActiveConfiguration();
1004   if (!config)
1005     return;
1006 
1007   for (const auto& map_entry : claimed_interfaces_) {
1008     CombinedInterfaceInfo interface_info = FindInterfaceInfoFromConfig(
1009         config, map_entry.first, map_entry.second->alternate_setting());
1010 
1011     if (!interface_info.IsValid())
1012       return;
1013 
1014     for (const auto& endpoint : interface_info.alternate->endpoints) {
1015       endpoint_map_[ConvertEndpointNumberToAddress(*endpoint)] = {
1016           interface_info.interface, endpoint.get()};
1017     }
1018   }
1019 }
1020 
1021 scoped_refptr<UsbDeviceHandleImpl::InterfaceClaimer>
GetClaimedInterfaceForEndpoint(uint8_t endpoint)1022 UsbDeviceHandleImpl::GetClaimedInterfaceForEndpoint(uint8_t endpoint) {
1023   const auto endpoint_it = endpoint_map_.find(endpoint);
1024   if (endpoint_it != endpoint_map_.end())
1025     return claimed_interfaces_[endpoint_it->second.interface->interface_number];
1026   return nullptr;
1027 }
1028 
ReportIsochronousTransferError(UsbDeviceHandle::IsochronousTransferCallback callback,const std::vector<uint32_t> packet_lengths,UsbTransferStatus status)1029 void UsbDeviceHandleImpl::ReportIsochronousTransferError(
1030     UsbDeviceHandle::IsochronousTransferCallback callback,
1031     const std::vector<uint32_t> packet_lengths,
1032     UsbTransferStatus status) {
1033   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
1034 
1035   std::vector<UsbIsochronousPacketPtr> packets(packet_lengths.size());
1036   for (size_t i = 0; i < packet_lengths.size(); ++i) {
1037     packets[i] = mojom::UsbIsochronousPacket::New();
1038     packets[i]->length = packet_lengths[i];
1039     packets[i]->transferred_length = 0;
1040     packets[i]->status = status;
1041   }
1042   task_runner_->PostTask(FROM_HERE, base::BindOnce(std::move(callback), nullptr,
1043                                                    std::move(packets)));
1044 }
1045 
SubmitTransfer(std::unique_ptr<Transfer> transfer)1046 void UsbDeviceHandleImpl::SubmitTransfer(std::unique_ptr<Transfer> transfer) {
1047   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
1048   DCHECK(transfer);
1049 
1050   // Transfer is owned by libusb until its completion callback is run. This
1051   // object holds a weak reference.
1052   transfers_.insert(transfer.get());
1053   blocking_task_runner_->PostTask(
1054       FROM_HERE,
1055       base::BindOnce(&Transfer::Submit, base::Unretained(transfer.release())));
1056 }
1057 
TransferComplete(Transfer * transfer,base::OnceClosure callback)1058 void UsbDeviceHandleImpl::TransferComplete(Transfer* transfer,
1059                                            base::OnceClosure callback) {
1060   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
1061   DCHECK(base::Contains(transfers_, transfer)) << "Missing transfer completed";
1062   transfers_.erase(transfer);
1063 
1064   std::move(callback).Run();
1065 
1066   // libusb_free_transfer races with libusb_submit_transfer and only work-
1067   // around is to make sure to call them on the same thread.
1068   blocking_task_runner_->DeleteSoon(FROM_HERE, transfer);
1069 }
1070 
1071 }  // namespace device
1072