diff options
| author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-07-12 14:07:37 +0200 |
|---|---|---|
| committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-07-17 10:29:26 +0000 |
| commit | ec02ee4181c49b61fce1c8fb99292dbb8139cc90 (patch) | |
| tree | 25cde714b2b71eb639d1cd53f5a22e9ba76e14ef /chromium/device/hid | |
| parent | bb09965444b5bb20b096a291445170876225268d (diff) | |
| download | qtwebengine-chromium-ec02ee4181c49b61fce1c8fb99292dbb8139cc90.tar.gz | |
BASELINE: Update Chromium to 59.0.3071.134
Change-Id: Id02ef6fb2204c5fd21668a1c3e6911c83b17585a
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/device/hid')
| -rw-r--r-- | chromium/device/hid/hid_connection.cc | 14 | ||||
| -rw-r--r-- | chromium/device/hid/hid_connection.h | 11 | ||||
| -rw-r--r-- | chromium/device/hid/hid_connection_linux.cc | 264 | ||||
| -rw-r--r-- | chromium/device/hid/hid_connection_linux.h | 51 | ||||
| -rw-r--r-- | chromium/device/hid/hid_connection_mac.cc | 19 | ||||
| -rw-r--r-- | chromium/device/hid/hid_connection_mac.h | 4 | ||||
| -rw-r--r-- | chromium/device/hid/hid_connection_win.cc | 37 | ||||
| -rw-r--r-- | chromium/device/hid/hid_service_linux.cc | 67 | ||||
| -rw-r--r-- | chromium/device/hid/hid_service_linux.h | 7 | ||||
| -rw-r--r-- | chromium/device/hid/hid_service_mac.cc | 181 | ||||
| -rw-r--r-- | chromium/device/hid/hid_service_mac.h | 16 | ||||
| -rw-r--r-- | chromium/device/hid/hid_service_win.cc | 39 | ||||
| -rw-r--r-- | chromium/device/hid/hid_service_win.h | 18 |
13 files changed, 320 insertions, 408 deletions
diff --git a/chromium/device/hid/hid_connection.cc b/chromium/device/hid/hid_connection.cc index 5a904fe7cfa..9d5ee20f20b 100644 --- a/chromium/device/hid/hid_connection.cc +++ b/chromium/device/hid/hid_connection.cc @@ -170,20 +170,6 @@ void HidConnection::SendFeatureReport(scoped_refptr<net::IOBuffer> buffer, PlatformSendFeatureReport(buffer, size, callback); } -bool HidConnection::CompleteRead(scoped_refptr<net::IOBuffer> buffer, - size_t size, - const ReadCallback& callback) { - DCHECK_GE(size, 1u); - uint8_t report_id = buffer->data()[0]; - if (IsReportIdProtected(report_id)) { - HID_LOG(EVENT) << "Filtered a protected input report."; - return false; - } - - callback.Run(true, buffer, size); - return true; -} - bool HidConnection::IsReportIdProtected(uint8_t report_id) { HidCollectionInfo collection_info; if (FindCollectionByReportId(device_info_->collections(), report_id, diff --git a/chromium/device/hid/hid_connection.h b/chromium/device/hid/hid_connection.h index 1bf8d2e3c2d..dbff1caf093 100644 --- a/chromium/device/hid/hid_connection.h +++ b/chromium/device/hid/hid_connection.h @@ -75,18 +75,9 @@ class HidConnection : public base::RefCountedThreadSafe<HidConnection> { size_t size, const WriteCallback& callback) = 0; - // PlatformRead implementation must call this method on read - // success, rather than directly running the callback. - // In case incoming buffer is empty or protected, it is filtered - // and this method returns false. Otherwise it runs the callback - // and returns true. - bool CompleteRead(scoped_refptr<net::IOBuffer> buffer, - size_t size, - const ReadCallback& callback); - - private: bool IsReportIdProtected(uint8_t report_id); + private: scoped_refptr<HidDeviceInfo> device_info_; bool has_protected_collection_; base::ThreadChecker thread_checker_; diff --git a/chromium/device/hid/hid_connection_linux.cc b/chromium/device/hid/hid_connection_linux.cc index 5172b0b39ea..62d06c35d6a 100644 --- a/chromium/device/hid/hid_connection_linux.cc +++ b/chromium/device/hid/hid_connection_linux.cc @@ -14,9 +14,8 @@ #include "base/bind.h" #include "base/files/file_descriptor_watcher_posix.h" -#include "base/files/file_path.h" #include "base/macros.h" -#include "base/message_loop/message_loop.h" +#include "base/memory/ptr_util.h" #include "base/posix/eintr_wrapper.h" #include "base/threading/thread_restrictions.h" #include "base/threading/thread_task_runner_handle.h" @@ -33,44 +32,91 @@ namespace device { -class HidConnectionLinux::FileThreadHelper - : public base::MessageLoop::DestructionObserver { +class HidConnectionLinux::FileThreadHelper { public: - FileThreadHelper(base::PlatformFile platform_file, + FileThreadHelper(base::ScopedFD fd, scoped_refptr<HidDeviceInfo> device_info, - base::WeakPtr<HidConnectionLinux> connection, - scoped_refptr<base::SingleThreadTaskRunner> task_runner) - : platform_file_(platform_file), + base::WeakPtr<HidConnectionLinux> connection) + : fd_(std::move(fd)), connection_(connection), - task_runner_(task_runner) { + origin_task_runner_(base::ThreadTaskRunnerHandle::Get()) { + sequence_checker_.DetachFromSequence(); // Report buffers must always have room for the report ID. report_buffer_size_ = device_info->max_input_report_size() + 1; has_report_id_ = device_info->has_report_id(); } - ~FileThreadHelper() override { - DCHECK(thread_checker_.CalledOnValidThread()); - base::MessageLoop::current()->RemoveDestructionObserver(this); - } + ~FileThreadHelper() { DCHECK(sequence_checker_.CalledOnValidSequence()); } // Starts the FileDescriptorWatcher that reads input events from the device. // Must be called on a thread that has a base::MessageLoopForIO. - static void Start(std::unique_ptr<FileThreadHelper> self) { + void Start() { + DCHECK(sequence_checker_.CalledOnValidSequence()); base::ThreadRestrictions::AssertIOAllowed(); - self->thread_checker_.DetachFromThread(); - self->file_watcher_ = base::FileDescriptorWatcher::WatchReadable( - self->platform_file_, - base::Bind(&FileThreadHelper::OnFileCanReadWithoutBlocking, - base::Unretained(self.get()))); + file_watcher_ = base::FileDescriptorWatcher::WatchReadable( + fd_.get(), base::Bind(&FileThreadHelper::OnFileCanReadWithoutBlocking, + base::Unretained(this))); + } + + void Write(scoped_refptr<net::IOBuffer> buffer, + size_t size, + const WriteCallback& callback) { + DCHECK(sequence_checker_.CalledOnValidSequence()); + ssize_t result = HANDLE_EINTR(write(fd_.get(), buffer->data(), size)); + if (result < 0) { + HID_PLOG(EVENT) << "Write failed"; + origin_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); + } else { + if (static_cast<size_t>(result) != size) + HID_LOG(EVENT) << "Incomplete HID write: " << result << " != " << size; + origin_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); + } + } + + void GetFeatureReport(uint8_t report_id, + scoped_refptr<net::IOBufferWithSize> buffer, + const ReadCallback& callback) { + DCHECK(sequence_checker_.CalledOnValidSequence()); + int result = HANDLE_EINTR( + ioctl(fd_.get(), HIDIOCGFEATURE(buffer->size()), buffer->data())); + if (result < 0) { + HID_PLOG(EVENT) << "Failed to get feature report"; + origin_task_runner_->PostTask(FROM_HERE, + base::Bind(callback, false, nullptr, 0)); + } else if (result == 0) { + HID_LOG(EVENT) << "Get feature result too short."; + origin_task_runner_->PostTask(FROM_HERE, + base::Bind(callback, false, nullptr, 0)); + } else if (report_id == 0) { + // Linux adds a 0 to the beginning of the data received from the device. + scoped_refptr<net::IOBuffer> copied_buffer(new net::IOBuffer(result - 1)); + memcpy(copied_buffer->data(), buffer->data() + 1, result - 1); + origin_task_runner_->PostTask( + FROM_HERE, base::Bind(callback, true, copied_buffer, result - 1)); + } else { + origin_task_runner_->PostTask(FROM_HERE, + base::Bind(callback, true, buffer, result)); + } + } - // |self| is now owned by the current message loop. - base::MessageLoop::current()->AddDestructionObserver(self.release()); + void SendFeatureReport(scoped_refptr<net::IOBuffer> buffer, + size_t size, + const WriteCallback& callback) { + DCHECK(sequence_checker_.CalledOnValidSequence()); + int result = + HANDLE_EINTR(ioctl(fd_.get(), HIDIOCSFEATURE(size), buffer->data())); + if (result < 0) { + HID_PLOG(EVENT) << "Failed to send feature report"; + origin_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); + } else { + origin_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); + } } private: void OnFileCanReadWithoutBlocking() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(sequence_checker_.CalledOnValidSequence()); scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(report_buffer_size_)); char* data = buffer->data(); @@ -82,7 +128,7 @@ class HidConnectionLinux::FileThreadHelper length--; } - ssize_t bytes_read = HANDLE_EINTR(read(platform_file_, data, length)); + ssize_t bytes_read = HANDLE_EINTR(read(fd_.get(), data, length)); if (bytes_read < 0) { if (errno != EAGAIN) { HID_PLOG(EVENT) << "Read failed"; @@ -100,23 +146,17 @@ class HidConnectionLinux::FileThreadHelper bytes_read++; } - task_runner_->PostTask(FROM_HERE, - base::Bind(&HidConnectionLinux::ProcessInputReport, - connection_, buffer, bytes_read)); + origin_task_runner_->PostTask( + FROM_HERE, base::Bind(&HidConnectionLinux::ProcessInputReport, + connection_, buffer, bytes_read)); } - // base::MessageLoop::DestructionObserver: - void WillDestroyCurrentMessageLoop() override { - DCHECK(thread_checker_.CalledOnValidThread()); - delete this; - } - - base::ThreadChecker thread_checker_; - base::PlatformFile platform_file_; + base::SequenceChecker sequence_checker_; + base::ScopedFD fd_; size_t report_buffer_size_; bool has_report_id_; base::WeakPtr<HidConnectionLinux> connection_; - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + const scoped_refptr<base::SequencedTaskRunner> origin_task_runner_; std::unique_ptr<base::FileDescriptorWatcher::Controller> file_watcher_; DISALLOW_COPY_AND_ASSIGN(FileThreadHelper); @@ -124,38 +164,28 @@ class HidConnectionLinux::FileThreadHelper HidConnectionLinux::HidConnectionLinux( scoped_refptr<HidDeviceInfo> device_info, - base::File device_file, - scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) + base::ScopedFD fd, + scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) : HidConnection(device_info), - file_task_runner_(file_task_runner), + blocking_task_runner_(std::move(blocking_task_runner)), weak_factory_(this) { - task_runner_ = base::ThreadTaskRunnerHandle::Get(); - device_file_ = std::move(device_file); - - // The helper is passed a weak pointer to this connection so that it can be - // cleaned up after the connection is closed. - std::unique_ptr<FileThreadHelper> helper( - new FileThreadHelper(device_file_.GetPlatformFile(), device_info, - weak_factory_.GetWeakPtr(), task_runner_)); - helper_ = helper.get(); - file_task_runner_->PostTask( - FROM_HERE, base::Bind(&FileThreadHelper::Start, base::Passed(&helper))); + helper_ = base::MakeUnique<FileThreadHelper>(std::move(fd), device_info, + weak_factory_.GetWeakPtr()); + blocking_task_runner_->PostTask( + FROM_HERE, + base::Bind(&FileThreadHelper::Start, base::Unretained(helper_.get()))); } HidConnectionLinux::~HidConnectionLinux() { - DCHECK(helper_ == nullptr); + DCHECK(sequence_checker_.CalledOnValidSequence()); } void HidConnectionLinux::PlatformClose() { - // By closing the device file on the FILE thread (1) the requirement that - // base::File::Close is called on a thread where I/O is allowed is satisfied - // and (2) any tasks posted to this task runner that refer to this file will + // By closing the device on the blocking task runner 1) the requirement that + // base::ScopedFD is destroyed on a thread where I/O is allowed is satisfied + // and 2) any tasks posted to this task runner that refer to this file will // complete before it is closed. - file_task_runner_->DeleteSoon(FROM_HERE, helper_); - helper_ = nullptr; - file_task_runner_->PostTask(FROM_HERE, - base::Bind(&HidConnectionLinux::CloseDevice, - base::Passed(&device_file_))); + blocking_task_runner_->DeleteSoon(FROM_HERE, helper_.release()); while (!pending_reads_.empty()) { pending_reads_.front().callback.Run(false, NULL, 0); @@ -175,13 +205,10 @@ void HidConnectionLinux::PlatformWrite(scoped_refptr<net::IOBuffer> buffer, const WriteCallback& callback) { // Linux expects the first byte of the buffer to always be a report ID so the // buffer can be used directly. - file_task_runner_->PostTask( + blocking_task_runner_->PostTask( FROM_HERE, - base::Bind(&HidConnectionLinux::BlockingWrite, - device_file_.GetPlatformFile(), buffer, size, - base::Bind(&HidConnectionLinux::FinishWrite, - weak_factory_.GetWeakPtr(), size, callback), - task_runner_)); + base::Bind(&FileThreadHelper::Write, base::Unretained(helper_.get()), + buffer, size, callback)); } void HidConnectionLinux::PlatformGetFeatureReport( @@ -194,14 +221,10 @@ void HidConnectionLinux::PlatformGetFeatureReport( new net::IOBufferWithSize(device_info()->max_feature_report_size() + 1)); buffer->data()[0] = report_id; - file_task_runner_->PostTask( + blocking_task_runner_->PostTask( FROM_HERE, - base::Bind( - &HidConnectionLinux::BlockingIoctl, device_file_.GetPlatformFile(), - HIDIOCGFEATURE(buffer->size()), buffer, - base::Bind(&HidConnectionLinux::FinishGetFeatureReport, - weak_factory_.GetWeakPtr(), report_id, buffer, callback), - task_runner_)); + base::Bind(&FileThreadHelper::GetFeatureReport, + base::Unretained(helper_.get()), report_id, buffer, callback)); } void HidConnectionLinux::PlatformSendFeatureReport( @@ -210,93 +233,21 @@ void HidConnectionLinux::PlatformSendFeatureReport( const WriteCallback& callback) { // Linux expects the first byte of the buffer to always be a report ID so the // buffer can be used directly. - file_task_runner_->PostTask( + blocking_task_runner_->PostTask( FROM_HERE, - base::Bind(&HidConnectionLinux::BlockingIoctl, - device_file_.GetPlatformFile(), HIDIOCSFEATURE(size), buffer, - base::Bind(&HidConnectionLinux::FinishSendFeatureReport, - weak_factory_.GetWeakPtr(), callback), - task_runner_)); -} - -void HidConnectionLinux::FinishWrite(size_t expected_size, - const WriteCallback& callback, - ssize_t result) { - if (result < 0) { - HID_PLOG(EVENT) << "Write failed"; - callback.Run(false); - } else { - if (static_cast<size_t>(result) != expected_size) { - HID_LOG(EVENT) << "Incomplete HID write: " << result - << " != " << expected_size; - } - callback.Run(true); - } -} - -void HidConnectionLinux::FinishGetFeatureReport( - uint8_t report_id, - scoped_refptr<net::IOBuffer> buffer, - const ReadCallback& callback, - int result) { - if (result < 0) { - HID_PLOG(EVENT) << "Failed to get feature report"; - callback.Run(false, NULL, 0); - } else if (result == 0) { - HID_LOG(EVENT) << "Get feature result too short."; - callback.Run(false, NULL, 0); - } else if (report_id == 0) { - // Linux adds a 0 to the beginning of the data received from the device. - scoped_refptr<net::IOBuffer> copied_buffer(new net::IOBuffer(result - 1)); - memcpy(copied_buffer->data(), buffer->data() + 1, result - 1); - callback.Run(true, copied_buffer, result - 1); - } else { - callback.Run(true, buffer, result); - } -} - -void HidConnectionLinux::FinishSendFeatureReport(const WriteCallback& callback, - int result) { - if (result < 0) { - HID_PLOG(EVENT) << "Failed to send feature report"; - callback.Run(false); - } else { - callback.Run(true); - } -} - -// static -void HidConnectionLinux::BlockingWrite( - base::PlatformFile platform_file, - scoped_refptr<net::IOBuffer> buffer, - size_t size, - const InternalWriteCallback& callback, - scoped_refptr<base::SingleThreadTaskRunner> task_runner) { - base::ThreadRestrictions::AssertIOAllowed(); - ssize_t result = HANDLE_EINTR(write(platform_file, buffer->data(), size)); - task_runner->PostTask(FROM_HERE, base::Bind(callback, result)); -} - -// static -void HidConnectionLinux::BlockingIoctl( - base::PlatformFile platform_file, - int request, - scoped_refptr<net::IOBuffer> buffer, - const IoctlCallback& callback, - scoped_refptr<base::SingleThreadTaskRunner> task_runner) { - base::ThreadRestrictions::AssertIOAllowed(); - int result = ioctl(platform_file, request, buffer->data()); - task_runner->PostTask(FROM_HERE, base::Bind(callback, result)); -} - -// static -void HidConnectionLinux::CloseDevice(base::File device_file) { - device_file.Close(); + base::Bind(&FileThreadHelper::SendFeatureReport, + base::Unretained(helper_.get()), buffer, size, callback)); } void HidConnectionLinux::ProcessInputReport(scoped_refptr<net::IOBuffer> buffer, size_t size) { DCHECK(thread_checker().CalledOnValidThread()); + DCHECK_GE(size, 1u); + + uint8_t report_id = buffer->data()[0]; + if (IsReportIdProtected(report_id)) + return; + PendingHidReport report; report.buffer = buffer; report.size = size; @@ -306,14 +257,17 @@ void HidConnectionLinux::ProcessInputReport(scoped_refptr<net::IOBuffer> buffer, void HidConnectionLinux::ProcessReadQueue() { DCHECK(thread_checker().CalledOnValidThread()); + + // Hold a reference to |this| to prevent a callback from freeing this object + // during the loop. + scoped_refptr<HidConnectionLinux> self(this); while (pending_reads_.size() && pending_reports_.size()) { PendingHidRead read = pending_reads_.front(); PendingHidReport report = pending_reports_.front(); + pending_reads_.pop(); pending_reports_.pop(); - if (CompleteRead(report.buffer, report.size, read.callback)) { - pending_reads_.pop(); - } + read.callback.Run(true, report.buffer, report.size); } } diff --git a/chromium/device/hid/hid_connection_linux.h b/chromium/device/hid/hid_connection_linux.h index bcdb99c1cc7..574c732638b 100644 --- a/chromium/device/hid/hid_connection_linux.h +++ b/chromium/device/hid/hid_connection_linux.h @@ -10,13 +10,14 @@ #include <queue> -#include "base/files/file.h" +#include "base/files/scoped_file.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "base/sequence_checker.h" #include "device/hid/hid_connection.h" namespace base { -class SingleThreadTaskRunner; +class SequencedTaskRunner; } namespace device { @@ -25,16 +26,13 @@ class HidConnectionLinux : public HidConnection { public: HidConnectionLinux( scoped_refptr<HidDeviceInfo> device_info, - base::File device_file, - scoped_refptr<base::SingleThreadTaskRunner> file_thread_runner); + base::ScopedFD fd, + scoped_refptr<base::SequencedTaskRunner> blocking_task_runner); private: friend class base::RefCountedThreadSafe<HidConnectionLinux>; class FileThreadHelper; - typedef base::Callback<void(ssize_t)> InternalWriteCallback; - typedef base::Callback<void(int)> IoctlCallback; - ~HidConnectionLinux() override; // HidConnection implementation. @@ -49,46 +47,21 @@ class HidConnectionLinux : public HidConnection { size_t size, const WriteCallback& callback) override; - // Callbacks for blocking operations run on the FILE thread. - void FinishWrite(size_t expected_size, - const WriteCallback& callback, - ssize_t result); - void FinishGetFeatureReport(uint8_t report_id, - scoped_refptr<net::IOBuffer> buffer, - const ReadCallback& callback, - int result); - void FinishSendFeatureReport(const WriteCallback& callback, int result); - - // Writes to the device. This operation may block. - static void BlockingWrite( - base::PlatformFile platform_file, - scoped_refptr<net::IOBuffer> buffer, - size_t size, - const InternalWriteCallback& callback, - scoped_refptr<base::SingleThreadTaskRunner> task_runner); - // Performs an ioctl on the device. This operation may block. - static void BlockingIoctl( - base::PlatformFile platform_file, - int request, - scoped_refptr<net::IOBuffer> buffer, - const IoctlCallback& callback, - scoped_refptr<base::SingleThreadTaskRunner> task_runner); - - // Closes the device file descriptor. Must be called on the FILE thread. - static void CloseDevice(base::File device_file); - void ProcessInputReport(scoped_refptr<net::IOBuffer> buffer, size_t size); void ProcessReadQueue(); - base::File device_file_; - FileThreadHelper* helper_; + // This object lives on the sequence to which |blocking_task_runner_| posts + // tasks so all calls must be posted there including this object's + // destruction. + std::unique_ptr<FileThreadHelper> helper_; - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_; + const scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_; std::queue<PendingHidReport> pending_reports_; std::queue<PendingHidRead> pending_reads_; + base::SequenceChecker sequence_checker_; + base::WeakPtrFactory<HidConnectionLinux> weak_factory_; DISALLOW_COPY_AND_ASSIGN(HidConnectionLinux); diff --git a/chromium/device/hid/hid_connection_mac.cc b/chromium/device/hid/hid_connection_mac.cc index 4aa4a8f3c5b..c13fc2b0d8c 100644 --- a/chromium/device/hid/hid_connection_mac.cc +++ b/chromium/device/hid/hid_connection_mac.cc @@ -25,11 +25,11 @@ std::string HexErrorCode(IOReturn error_code) { } // namespace HidConnectionMac::HidConnectionMac( - IOHIDDeviceRef device, + base::ScopedCFTypeRef<IOHIDDeviceRef> device, scoped_refptr<HidDeviceInfo> device_info, scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) : HidConnection(device_info), - device_(device, base::scoped_policy::RETAIN), + device_(std::move(device)), file_task_runner_(file_task_runner) { task_runner_ = base::ThreadTaskRunnerHandle::Get(); DCHECK(task_runner_.get()); @@ -152,6 +152,12 @@ void HidConnectionMac::InputReportCallback(void* context, void HidConnectionMac::ProcessInputReport( scoped_refptr<net::IOBufferWithSize> buffer) { DCHECK(thread_checker().CalledOnValidThread()); + DCHECK_GE(buffer->size(), 1); + + uint8_t report_id = buffer->data()[0]; + if (IsReportIdProtected(report_id)) + return; + PendingHidReport report; report.buffer = buffer; report.size = buffer->size(); @@ -161,14 +167,17 @@ void HidConnectionMac::ProcessInputReport( void HidConnectionMac::ProcessReadQueue() { DCHECK(thread_checker().CalledOnValidThread()); + + // Hold a reference to |this| to prevent a callback from freeing this object + // during the loop. + scoped_refptr<HidConnectionMac> self(this); while (pending_reads_.size() && pending_reports_.size()) { PendingHidRead read = pending_reads_.front(); PendingHidReport report = pending_reports_.front(); + pending_reads_.pop(); pending_reports_.pop(); - if (CompleteRead(report.buffer, report.size, read.callback)) { - pending_reads_.pop(); - } + read.callback.Run(true, report.buffer, report.size); } } diff --git a/chromium/device/hid/hid_connection_mac.h b/chromium/device/hid/hid_connection_mac.h index c3ea163b39f..da0dacd501c 100644 --- a/chromium/device/hid/hid_connection_mac.h +++ b/chromium/device/hid/hid_connection_mac.h @@ -6,7 +6,7 @@ #define DEVICE_HID_HID_CONNECTION_MAC_H_ #include <CoreFoundation/CoreFoundation.h> -#include <IOKit/hid/IOHIDManager.h> +#include <IOKit/hid/IOHIDDevice.h> #include <stddef.h> #include <stdint.h> @@ -29,7 +29,7 @@ namespace device { class HidConnectionMac : public HidConnection { public: HidConnectionMac( - IOHIDDeviceRef device, + base::ScopedCFTypeRef<IOHIDDeviceRef> device, scoped_refptr<HidDeviceInfo> device_info, scoped_refptr<base::SingleThreadTaskRunner> file_task_runner); diff --git a/chromium/device/hid/hid_connection_win.cc b/chromium/device/hid/hid_connection_win.cc index a98007ae095..ad4ca2a26f8 100644 --- a/chromium/device/hid/hid_connection_win.cc +++ b/chromium/device/hid/hid_connection_win.cc @@ -11,7 +11,6 @@ #include "base/files/file.h" #include "base/macros.h" #include "base/memory/ptr_util.h" -#include "base/message_loop/message_loop.h" #include "base/numerics/safe_conversions.h" #include "base/win/object_watcher.h" #include "components/device_event_log/device_event_log.h" @@ -30,8 +29,7 @@ extern "C" { namespace device { -class PendingHidTransfer : public base::win::ObjectWatcher::Delegate, - public base::MessageLoop::DestructionObserver { +class PendingHidTransfer : public base::win::ObjectWatcher::Delegate { public: typedef base::OnceCallback<void(PendingHidTransfer*, bool)> Callback; @@ -45,9 +43,6 @@ class PendingHidTransfer : public base::win::ObjectWatcher::Delegate, // Implements base::win::ObjectWatcher::Delegate. void OnObjectSignaled(HANDLE object) override; - // Implements base::MessageLoop::DestructionObserver - void WillDestroyCurrentMessageLoop() override; - private: // The buffer isn't used by this object but it's important that a reference // to it is held until the transfer completes. @@ -70,7 +65,6 @@ PendingHidTransfer::PendingHidTransfer(scoped_refptr<net::IOBuffer> buffer, } PendingHidTransfer::~PendingHidTransfer() { - base::MessageLoop::current()->RemoveDestructionObserver(this); if (callback_) std::move(callback_).Run(this, false); } @@ -79,7 +73,6 @@ void PendingHidTransfer::TakeResultFromWindowsAPI(BOOL result) { if (result) { std::move(callback_).Run(this, true); } else if (GetLastError() == ERROR_IO_PENDING) { - base::MessageLoop::current()->AddDestructionObserver(this); watcher_.StartWatchingOnce(event_.Get(), this); } else { HID_PLOG(EVENT) << "HID transfer failed"; @@ -91,14 +84,9 @@ void PendingHidTransfer::OnObjectSignaled(HANDLE event_handle) { std::move(callback_).Run(this, true); } -void PendingHidTransfer::WillDestroyCurrentMessageLoop() { - watcher_.StopWatching(); - std::move(callback_).Run(this, false); -} - HidConnectionWin::HidConnectionWin(scoped_refptr<HidDeviceInfo> device_info, base::win::ScopedHandle file) - : HidConnection(device_info), file_(std::move(file)) {} + : HidConnection(std::move(device_info)), file_(std::move(file)) {} HidConnectionWin::~HidConnectionWin() { DCHECK(!file_.IsValid()); @@ -191,13 +179,26 @@ void HidConnectionWin::OnReadComplete(scoped_refptr<net::IOBuffer> buffer, std::unique_ptr<PendingHidTransfer> transfer = UnlinkTransfer(transfer_raw); DWORD bytes_transferred; - if (signaled && GetOverlappedResult(file_.Get(), transfer->GetOverlapped(), - &bytes_transferred, FALSE)) { - CompleteRead(buffer, bytes_transferred, callback); - } else { + if (!signaled || !GetOverlappedResult(file_.Get(), transfer->GetOverlapped(), + &bytes_transferred, FALSE)) { HID_PLOG(EVENT) << "HID read failed"; callback.Run(false, nullptr, 0); + return; } + + if (bytes_transferred < 1) { + HID_LOG(EVENT) << "HID read too short."; + callback.Run(false, nullptr, 0); + return; + } + + uint8_t report_id = buffer->data()[0]; + if (IsReportIdProtected(report_id)) { + PlatformRead(callback); + return; + } + + callback.Run(true, buffer, bytes_transferred); } void HidConnectionWin::OnReadFeatureComplete( diff --git a/chromium/device/hid/hid_service_linux.cc b/chromium/device/hid/hid_service_linux.cc index 1cd5d393b17..6b524466403 100644 --- a/chromium/device/hid/hid_service_linux.cc +++ b/chromium/device/hid/hid_service_linux.cc @@ -16,6 +16,7 @@ #include "base/files/file.h" #include "base/files/file_path.h" #include "base/files/file_util.h" +#include "base/files/scoped_file.h" #include "base/location.h" #include "base/macros.h" #include "base/memory/ptr_util.h" @@ -52,25 +53,25 @@ const char kSysfsReportDescriptorKey[] = "report_descriptor"; struct HidServiceLinux::ConnectParams { ConnectParams(scoped_refptr<HidDeviceInfoLinux> device_info, const ConnectCallback& callback, - scoped_refptr<base::SingleThreadTaskRunner> task_runner, - scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) - : device_info(device_info), + scoped_refptr<base::SequencedTaskRunner> task_runner, + scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) + : device_info(std::move(device_info)), callback(callback), - task_runner(task_runner), - file_task_runner(file_task_runner) {} + task_runner(std::move(task_runner)), + blocking_task_runner(std::move(blocking_task_runner)) {} ~ConnectParams() {} scoped_refptr<HidDeviceInfoLinux> device_info; ConnectCallback callback; - scoped_refptr<base::SingleThreadTaskRunner> task_runner; - scoped_refptr<base::SingleThreadTaskRunner> file_task_runner; - base::File device_file; + scoped_refptr<base::SequencedTaskRunner> task_runner; + scoped_refptr<base::SequencedTaskRunner> blocking_task_runner; + base::ScopedFD fd; }; class HidServiceLinux::FileThreadHelper : public DeviceMonitorLinux::Observer { public: FileThreadHelper(base::WeakPtr<HidServiceLinux> service, - scoped_refptr<base::SingleThreadTaskRunner> task_runner) + scoped_refptr<base::SequencedTaskRunner> task_runner) : observer_(this), service_(service), task_runner_(task_runner) { thread_checker_.DetachFromThread(); } @@ -192,18 +193,19 @@ class HidServiceLinux::FileThreadHelper : public DeviceMonitorLinux::Observer { // This weak pointer is only valid when checked on this task runner. base::WeakPtr<HidServiceLinux> service_; - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + scoped_refptr<base::SequencedTaskRunner> task_runner_; DISALLOW_COPY_AND_ASSIGN(FileThreadHelper); }; HidServiceLinux::HidServiceLinux( - scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) - : file_task_runner_(std::move(file_task_runner)), weak_factory_(this) { - task_runner_ = base::ThreadTaskRunnerHandle::Get(); + scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) + : task_runner_(base::ThreadTaskRunnerHandle::Get()), + blocking_task_runner_(std::move(blocking_task_runner)), + weak_factory_(this) { helper_ = base::MakeUnique<FileThreadHelper>(weak_factory_.GetWeakPtr(), task_runner_); - file_task_runner_->PostTask( + blocking_task_runner_->PostTask( FROM_HERE, base::Bind(&FileThreadHelper::Start, base::Unretained(helper_.get()))); } @@ -214,7 +216,7 @@ HidServiceLinux::~HidServiceLinux() { void HidServiceLinux::Shutdown() { const bool did_post_task = - file_task_runner_->DeleteSoon(FROM_HERE, helper_.release()); + blocking_task_runner_->DeleteSoon(FROM_HERE, helper_.release()); DCHECK(did_post_task); HidService::Shutdown(); } @@ -232,7 +234,7 @@ void HidServiceLinux::Connect(const HidDeviceId& device_id, static_cast<HidDeviceInfoLinux*>(map_entry->second.get()); std::unique_ptr<ConnectParams> params(new ConnectParams( - device_info, callback, task_runner_, file_task_runner_)); + device_info, callback, task_runner_, blocking_task_runner_)); #if defined(OS_CHROMEOS) chromeos::PermissionBrokerClient* client = @@ -246,9 +248,9 @@ void HidServiceLinux::Connect(const HidDeviceId& device_id, base::Bind(&HidServiceLinux::OnPathOpenComplete, base::Passed(¶ms)), error_callback); #else - file_task_runner_->PostTask(FROM_HERE, - base::Bind(&HidServiceLinux::OpenOnBlockingThread, - base::Passed(¶ms))); + blocking_task_runner_->PostTask( + FROM_HERE, base::Bind(&HidServiceLinux::OpenOnBlockingThread, + base::Passed(¶ms))); #endif // defined(OS_CHROMEOS) } @@ -257,11 +259,12 @@ void HidServiceLinux::Connect(const HidDeviceId& device_id, // static void HidServiceLinux::OnPathOpenComplete(std::unique_ptr<ConnectParams> params, base::ScopedFD fd) { - scoped_refptr<base::SingleThreadTaskRunner> file_task_runner = - params->file_task_runner; - params->device_file = base::File(fd.release()); - file_task_runner->PostTask(FROM_HERE, base::Bind(&HidServiceLinux::FinishOpen, - base::Passed(¶ms))); + scoped_refptr<base::SequencedTaskRunner> blocking_task_runner = + params->blocking_task_runner; + params->fd = std::move(fd); + blocking_task_runner->PostTask( + FROM_HERE, + base::Bind(&HidServiceLinux::FinishOpen, base::Passed(¶ms))); } // static @@ -280,10 +283,10 @@ void HidServiceLinux::OnPathOpenError(const std::string& device_path, void HidServiceLinux::OpenOnBlockingThread( std::unique_ptr<ConnectParams> params) { base::ThreadRestrictions::AssertIOAllowed(); - scoped_refptr<base::SingleThreadTaskRunner> task_runner = params->task_runner; + scoped_refptr<base::SequencedTaskRunner> task_runner = params->task_runner; base::FilePath device_path(params->device_info->device_node()); - base::File& device_file = params->device_file; + base::File device_file; int flags = base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE; device_file.Initialize(device_path, flags); @@ -304,7 +307,7 @@ void HidServiceLinux::OpenOnBlockingThread( task_runner->PostTask(FROM_HERE, base::Bind(params->callback, nullptr)); return; } - + params->fd.reset(device_file.TakePlatformFile()); FinishOpen(std::move(params)); } @@ -313,9 +316,9 @@ void HidServiceLinux::OpenOnBlockingThread( // static void HidServiceLinux::FinishOpen(std::unique_ptr<ConnectParams> params) { base::ThreadRestrictions::AssertIOAllowed(); - scoped_refptr<base::SingleThreadTaskRunner> task_runner = params->task_runner; + scoped_refptr<base::SequencedTaskRunner> task_runner = params->task_runner; - if (!base::SetNonBlocking(params->device_file.GetPlatformFile())) { + if (!base::SetNonBlocking(params->fd.get())) { HID_PLOG(ERROR) << "Failed to set the non-blocking flag on the device fd"; task_runner->PostTask(FROM_HERE, base::Bind(params->callback, nullptr)); return; @@ -328,10 +331,10 @@ void HidServiceLinux::FinishOpen(std::unique_ptr<ConnectParams> params) { // static void HidServiceLinux::CreateConnection(std::unique_ptr<ConnectParams> params) { - DCHECK(params->device_file.IsValid()); + DCHECK(params->fd.is_valid()); params->callback.Run(make_scoped_refptr(new HidConnectionLinux( - params->device_info, std::move(params->device_file), - params->file_task_runner))); + std::move(params->device_info), std::move(params->fd), + std::move(params->blocking_task_runner)))); } } // namespace device diff --git a/chromium/device/hid/hid_service_linux.h b/chromium/device/hid/hid_service_linux.h index 5f8084f8bf8..17616ba6699 100644 --- a/chromium/device/hid/hid_service_linux.h +++ b/chromium/device/hid/hid_service_linux.h @@ -19,7 +19,8 @@ namespace device { class HidServiceLinux : public HidService { public: - HidServiceLinux(scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner); + HidServiceLinux( + scoped_refptr<base::SequencedTaskRunner> blocking_task_runner); ~HidServiceLinux() override; // HidService: @@ -48,8 +49,8 @@ class HidServiceLinux : public HidService { static void FinishOpen(std::unique_ptr<ConnectParams> params); static void CreateConnection(std::unique_ptr<ConnectParams> params); - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_; + const scoped_refptr<base::SequencedTaskRunner> task_runner_; + const scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_; // The helper lives on the FILE thread and holds a weak reference back to the // service that owns it. diff --git a/chromium/device/hid/hid_service_mac.cc b/chromium/device/hid/hid_service_mac.cc index d887eeee947..92d1617b9ff 100644 --- a/chromium/device/hid/hid_service_mac.cc +++ b/chromium/device/hid/hid_service_mac.cc @@ -5,7 +5,6 @@ #include "device/hid/hid_service_mac.h" #include <CoreFoundation/CoreFoundation.h> -#include <IOKit/hid/IOHIDDevice.h> #include <stdint.h> #include <set> @@ -33,58 +32,67 @@ std::string HexErrorCode(IOReturn error_code) { return base::StringPrintf("0x%04x", error_code); } -bool TryGetHidIntProperty(IOHIDDeviceRef device, - CFStringRef key, - int32_t* result) { - CFNumberRef ref = - base::mac::CFCast<CFNumberRef>(IOHIDDeviceGetProperty(device, key)); - return ref && CFNumberGetValue(ref, kCFNumberSInt32Type, result); -} - -int32_t GetHidIntProperty(IOHIDDeviceRef device, CFStringRef key) { - int32_t value; - if (TryGetHidIntProperty(device, key, &value)) - return value; +int32_t GetIntProperty(io_service_t service, CFStringRef key) { + base::ScopedCFTypeRef<CFNumberRef> ref(base::mac::CFCast<CFNumberRef>( + IORegistryEntryCreateCFProperty(service, key, kCFAllocatorDefault, 0))); + int32_t result; + if (ref && CFNumberGetValue(ref, kCFNumberSInt32Type, &result)) + return result; return 0; } -bool TryGetHidStringProperty(IOHIDDeviceRef device, - CFStringRef key, - std::string* result) { - CFStringRef ref = - base::mac::CFCast<CFStringRef>(IOHIDDeviceGetProperty(device, key)); - if (!ref) { - return false; - } - *result = base::SysCFStringRefToUTF8(ref); - return true; -} - -std::string GetHidStringProperty(IOHIDDeviceRef device, CFStringRef key) { - std::string value; - TryGetHidStringProperty(device, key, &value); - return value; +std::string GetStringProperty(io_service_t service, CFStringRef key) { + base::ScopedCFTypeRef<CFStringRef> ref(base::mac::CFCast<CFStringRef>( + IORegistryEntryCreateCFProperty(service, key, kCFAllocatorDefault, 0))); + if (ref) + return base::SysCFStringRefToUTF8(ref); + return std::string(); } -bool TryGetHidDataProperty(IOHIDDeviceRef device, +bool TryGetHidDataProperty(io_service_t service, CFStringRef key, std::vector<uint8_t>* result) { - CFDataRef ref = - base::mac::CFCast<CFDataRef>(IOHIDDeviceGetProperty(device, key)); - if (!ref) { + base::ScopedCFTypeRef<CFDataRef> ref(base::mac::CFCast<CFDataRef>( + IORegistryEntryCreateCFProperty(service, key, kCFAllocatorDefault, 0))); + if (!ref) return false; - } + base::STLClearObject(result); const uint8_t* bytes = CFDataGetBytePtr(ref); result->insert(result->begin(), bytes, bytes + CFDataGetLength(ref)); return true; } +scoped_refptr<HidDeviceInfo> CreateDeviceInfo( + base::mac::ScopedIOObject<io_service_t> service) { + uint64_t entry_id; + IOReturn result = IORegistryEntryGetRegistryEntryID(service, &entry_id); + if (result != kIOReturnSuccess) { + HID_LOG(EVENT) << "Failed to get IORegistryEntry ID: " + << HexErrorCode(result); + return nullptr; + } + + std::vector<uint8_t> report_descriptor; + if (!TryGetHidDataProperty(service, CFSTR(kIOHIDReportDescriptorKey), + &report_descriptor)) { + HID_LOG(DEBUG) << "Device report descriptor not available."; + } + + return new HidDeviceInfo( + entry_id, GetIntProperty(service, CFSTR(kIOHIDVendorIDKey)), + GetIntProperty(service, CFSTR(kIOHIDProductIDKey)), + GetStringProperty(service, CFSTR(kIOHIDProductKey)), + GetStringProperty(service, CFSTR(kIOHIDSerialNumberKey)), + kHIDBusTypeUSB, // TODO(reillyg): Detect Bluetooth. crbug.com/443335 + report_descriptor); +} + } // namespace HidServiceMac::HidServiceMac( scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) - : file_task_runner_(file_task_runner) { + : file_task_runner_(file_task_runner), weak_factory_(this) { task_runner_ = base::ThreadTaskRunnerHandle::Get(); DCHECK(task_runner_.get()); @@ -132,14 +140,25 @@ void HidServiceMac::Connect(const HidDeviceId& device_id, task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr)); return; } - scoped_refptr<HidDeviceInfo> device_info = map_entry->second; + file_task_runner_->PostTask( + FROM_HERE, + base::Bind(&HidServiceMac::OpenOnBlockingThread, map_entry->second, + task_runner_, weak_factory_.GetWeakPtr(), callback)); +} + +// static +void HidServiceMac::OpenOnBlockingThread( + scoped_refptr<HidDeviceInfo> device_info, + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + base::WeakPtr<HidServiceMac> hid_service, + const ConnectCallback& callback) { base::ScopedCFTypeRef<CFDictionaryRef> matching_dict( - IORegistryEntryIDMatching(device_id)); + IORegistryEntryIDMatching(device_info->device_id())); if (!matching_dict.get()) { HID_LOG(EVENT) << "Failed to create matching dictionary for ID: " - << device_id; - task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr)); + << device_info->device_id(); + task_runner->PostTask(FROM_HERE, base::Bind(callback, nullptr)); return; } @@ -148,8 +167,9 @@ void HidServiceMac::Connect(const HidDeviceId& device_id, base::mac::ScopedIOObject<io_service_t> service(IOServiceGetMatchingService( kIOMasterPortDefault, matching_dict.release())); if (!service.get()) { - HID_LOG(EVENT) << "IOService not found for ID: " << device_id; - task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr)); + HID_LOG(EVENT) << "IOService not found for ID: " + << device_info->device_id(); + task_runner->PostTask(FROM_HERE, base::Bind(callback, nullptr)); return; } @@ -157,21 +177,28 @@ void HidServiceMac::Connect(const HidDeviceId& device_id, IOHIDDeviceCreate(kCFAllocatorDefault, service)); if (!hid_device) { HID_LOG(EVENT) << "Unable to create IOHIDDevice object."; - task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr)); + task_runner->PostTask(FROM_HERE, base::Bind(callback, nullptr)); return; } IOReturn result = IOHIDDeviceOpen(hid_device, kIOHIDOptionsTypeNone); if (result != kIOReturnSuccess) { HID_LOG(EVENT) << "Failed to open device: " << HexErrorCode(result); - task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr)); + task_runner->PostTask(FROM_HERE, base::Bind(callback, nullptr)); return; } - task_runner_->PostTask( - FROM_HERE, base::Bind(callback, make_scoped_refptr(new HidConnectionMac( - hid_device.release(), device_info, - file_task_runner_)))); + task_runner->PostTask( + FROM_HERE, base::Bind(&HidServiceMac::DeviceOpened, hid_service, + device_info, base::Passed(&hid_device), callback)); +} + +void HidServiceMac::DeviceOpened( + scoped_refptr<HidDeviceInfo> device_info, + base::ScopedCFTypeRef<IOHIDDeviceRef> hid_device, + const ConnectCallback& callback) { + callback.Run(make_scoped_refptr(new HidConnectionMac( + std::move(hid_device), std::move(device_info), file_task_runner_))); } // static @@ -193,69 +220,25 @@ void HidServiceMac::TerminatedCallback(void* context, io_iterator_t iterator) { void HidServiceMac::AddDevices() { DCHECK(thread_checker_.CalledOnValidThread()); - io_service_t device; - while ((device = IOIteratorNext(devices_added_iterator_)) != IO_OBJECT_NULL) { - scoped_refptr<HidDeviceInfo> device_info = CreateDeviceInfo(device); - if (device_info) { + base::mac::ScopedIOObject<io_service_t> device; + while (device.reset(IOIteratorNext(devices_added_iterator_)), device) { + scoped_refptr<HidDeviceInfo> device_info = + CreateDeviceInfo(std::move(device)); + if (device_info) AddDevice(device_info); - // The reference retained by IOIteratorNext is released below in - // RemoveDevices when the device is removed. - } else { - IOObjectRelease(device); - } } } void HidServiceMac::RemoveDevices() { DCHECK(thread_checker_.CalledOnValidThread()); - io_service_t device; - while ((device = IOIteratorNext(devices_removed_iterator_)) != - IO_OBJECT_NULL) { + base::mac::ScopedIOObject<io_service_t> device; + while (device.reset(IOIteratorNext(devices_removed_iterator_)), device) { uint64_t entry_id; IOReturn result = IORegistryEntryGetRegistryEntryID(device, &entry_id); - if (result == kIOReturnSuccess) { + if (result == kIOReturnSuccess) RemoveDevice(entry_id); - } - - // Release reference retained by AddDevices above. - IOObjectRelease(device); - // Release the reference retained by IOIteratorNext. - IOObjectRelease(device); - } -} - -// static -scoped_refptr<HidDeviceInfo> HidServiceMac::CreateDeviceInfo( - io_service_t service) { - uint64_t entry_id; - IOReturn result = IORegistryEntryGetRegistryEntryID(service, &entry_id); - if (result != kIOReturnSuccess) { - HID_LOG(EVENT) << "Failed to get IORegistryEntry ID: " - << HexErrorCode(result); - return nullptr; } - - base::ScopedCFTypeRef<IOHIDDeviceRef> hid_device( - IOHIDDeviceCreate(kCFAllocatorDefault, service)); - if (!hid_device) { - HID_LOG(EVENT) << "Unable to create IOHIDDevice object for new device."; - return nullptr; - } - - std::vector<uint8_t> report_descriptor; - if (!TryGetHidDataProperty(hid_device, CFSTR(kIOHIDReportDescriptorKey), - &report_descriptor)) { - HID_LOG(DEBUG) << "Device report descriptor not available."; - } - - return new HidDeviceInfo( - entry_id, GetHidIntProperty(hid_device, CFSTR(kIOHIDVendorIDKey)), - GetHidIntProperty(hid_device, CFSTR(kIOHIDProductIDKey)), - GetHidStringProperty(hid_device, CFSTR(kIOHIDProductKey)), - GetHidStringProperty(hid_device, CFSTR(kIOHIDSerialNumberKey)), - kHIDBusTypeUSB, // TODO(reillyg): Detect Bluetooth. crbug.com/443335 - report_descriptor); } } // namespace device diff --git a/chromium/device/hid/hid_service_mac.h b/chromium/device/hid/hid_service_mac.h index f3af539a252..7d6c0531d50 100644 --- a/chromium/device/hid/hid_service_mac.h +++ b/chromium/device/hid/hid_service_mac.h @@ -7,6 +7,7 @@ #include <CoreFoundation/CoreFoundation.h> #include <IOKit/IOKitLib.h> +#include <IOKit/hid/IOHIDDevice.h> #include <string> @@ -15,6 +16,7 @@ #include "base/mac/scoped_ioobject.h" #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" #include "device/hid/hid_service.h" namespace base { @@ -32,6 +34,15 @@ class HidServiceMac : public HidService { const ConnectCallback& connect) override; private: + static void OpenOnBlockingThread( + scoped_refptr<HidDeviceInfo> device_info, + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + base::WeakPtr<HidServiceMac> hid_service, + const ConnectCallback& callback); + void DeviceOpened(scoped_refptr<HidDeviceInfo> device_info, + base::ScopedCFTypeRef<IOHIDDeviceRef> hid_device, + const ConnectCallback& callback); + // IOService matching callbacks. static void FirstMatchCallback(void* context, io_iterator_t iterator); static void TerminatedCallback(void* context, io_iterator_t iterator); @@ -39,9 +50,6 @@ class HidServiceMac : public HidService { void AddDevices(); void RemoveDevices(); - static scoped_refptr<device::HidDeviceInfo> CreateDeviceInfo( - io_service_t device); - // Platform notification port. base::mac::ScopedIONotificationPortRef notify_port_; base::mac::ScopedIOObject<io_iterator_t> devices_added_iterator_; @@ -54,6 +62,8 @@ class HidServiceMac : public HidService { // on which slow running I/O operations can be performed. scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_; + base::WeakPtrFactory<HidServiceMac> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(HidServiceMac); }; diff --git a/chromium/device/hid/hid_service_win.cc b/chromium/device/hid/hid_service_win.cc index 3bbc657562b..a7f252eefd4 100644 --- a/chromium/device/hid/hid_service_win.cc +++ b/chromium/device/hid/hid_service_win.cc @@ -19,11 +19,10 @@ #include "base/files/file.h" #include "base/location.h" #include "base/memory/free_deleter.h" -#include "base/single_thread_task_runner.h" +#include "base/sequenced_task_runner.h" #include "base/strings/string_util.h" #include "base/strings/sys_string_conversions.h" -#include "base/threading/thread_restrictions.h" -#include "base/threading/thread_task_runner_handle.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "components/device_event_log/device_event_log.h" #include "device/hid/hid_connection_win.h" #include "device/hid/hid_device_info.h" @@ -32,19 +31,18 @@ namespace device { HidServiceWin::HidServiceWin( - scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) - : file_task_runner_(file_task_runner), + scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) + : task_runner_(base::SequencedTaskRunnerHandle::Get()), + blocking_task_runner_(std::move(blocking_task_runner)), device_observer_(this), weak_factory_(this) { - task_runner_ = base::ThreadTaskRunnerHandle::Get(); - DCHECK(task_runner_.get()); DeviceMonitorWin* device_monitor = DeviceMonitorWin::GetForDeviceInterface(GUID_DEVINTERFACE_HID); - if (device_monitor) { + if (device_monitor) device_observer_.Add(device_monitor); - } - file_task_runner_->PostTask( - FROM_HERE, base::Bind(&HidServiceWin::EnumerateOnFileThread, + + blocking_task_runner_->PostTask( + FROM_HERE, base::Bind(&HidServiceWin::EnumerateBlocking, weak_factory_.GetWeakPtr(), task_runner_)); } @@ -74,9 +72,9 @@ void HidServiceWin::Connect(const HidDeviceId& device_id, } // static -void HidServiceWin::EnumerateOnFileThread( +void HidServiceWin::EnumerateBlocking( base::WeakPtr<HidServiceWin> service, - scoped_refptr<base::SingleThreadTaskRunner> task_runner) { + scoped_refptr<base::SequencedTaskRunner> task_runner) { HDEVINFO device_info_set = SetupDiGetClassDevs(&GUID_DEVINTERFACE_HID, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); @@ -115,8 +113,7 @@ void HidServiceWin::EnumerateOnFileThread( std::string device_path( base::SysWideToUTF8(device_interface_detail_data->DevicePath)); DCHECK(base::IsStringASCII(device_path)); - AddDeviceOnFileThread(service, task_runner, - base::ToLowerASCII(device_path)); + AddDeviceBlocking(service, task_runner, base::ToLowerASCII(device_path)); } } @@ -170,9 +167,9 @@ void HidServiceWin::CollectInfoFromValueCaps( } // static -void HidServiceWin::AddDeviceOnFileThread( +void HidServiceWin::AddDeviceBlocking( base::WeakPtr<HidServiceWin> service, - scoped_refptr<base::SingleThreadTaskRunner> task_runner, + scoped_refptr<base::SequencedTaskRunner> task_runner, const std::string& device_path) { base::win::ScopedHandle device_handle(OpenDevice(device_path)); if (!device_handle.IsValid()) { @@ -270,17 +267,17 @@ void HidServiceWin::AddDeviceOnFileThread( void HidServiceWin::OnDeviceAdded(const GUID& class_guid, const std::string& device_path) { - file_task_runner_->PostTask( + blocking_task_runner_->PostTask( FROM_HERE, - base::Bind(&HidServiceWin::AddDeviceOnFileThread, - weak_factory_.GetWeakPtr(), task_runner_, device_path)); + base::Bind(&HidServiceWin::AddDeviceBlocking, weak_factory_.GetWeakPtr(), + task_runner_, device_path)); } void HidServiceWin::OnDeviceRemoved(const GUID& class_guid, const std::string& device_path) { // Execute a no-op closure on the file task runner to synchronize with any // devices that are still being enumerated. - file_task_runner_->PostTaskAndReply( + blocking_task_runner_->PostTaskAndReply( FROM_HERE, base::Bind(&base::DoNothing), base::Bind(&HidServiceWin::RemoveDevice, weak_factory_.GetWeakPtr(), device_path)); diff --git a/chromium/device/hid/hid_service_win.h b/chromium/device/hid/hid_service_win.h index c8814f986d4..519f8ed5b39 100644 --- a/chromium/device/hid/hid_service_win.h +++ b/chromium/device/hid/hid_service_win.h @@ -23,20 +23,24 @@ extern "C" { #include "device/hid/hid_device_info.h" #include "device/hid/hid_service.h" +namespace base { +class SequencedTaskRunner; +} + namespace device { class HidServiceWin : public HidService, public DeviceMonitorWin::Observer { public: - HidServiceWin(scoped_refptr<base::SingleThreadTaskRunner> file_task_runner); + HidServiceWin(scoped_refptr<base::SequencedTaskRunner> blocking_task_runner); ~HidServiceWin() override; void Connect(const HidDeviceId& device_id, const ConnectCallback& callback) override; private: - static void EnumerateOnFileThread( + static void EnumerateBlocking( base::WeakPtr<HidServiceWin> service, - scoped_refptr<base::SingleThreadTaskRunner> task_runner); + scoped_refptr<base::SequencedTaskRunner> task_runner); static void CollectInfoFromButtonCaps(PHIDP_PREPARSED_DATA preparsed_data, HIDP_REPORT_TYPE report_type, USHORT button_caps_length, @@ -45,9 +49,9 @@ class HidServiceWin : public HidService, public DeviceMonitorWin::Observer { HIDP_REPORT_TYPE report_type, USHORT value_caps_length, HidCollectionInfo* collection_info); - static void AddDeviceOnFileThread( + static void AddDeviceBlocking( base::WeakPtr<HidServiceWin> service, - scoped_refptr<base::SingleThreadTaskRunner> task_runner, + scoped_refptr<base::SequencedTaskRunner> task_runner, const std::string& device_path); // DeviceMonitorWin::Observer implementation: @@ -59,8 +63,8 @@ class HidServiceWin : public HidService, public DeviceMonitorWin::Observer { // Tries to open the device read-write and falls back to read-only. static base::win::ScopedHandle OpenDevice(const std::string& device_path); - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_; + const scoped_refptr<base::SequencedTaskRunner> task_runner_; + const scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_; ScopedObserver<DeviceMonitorWin, DeviceMonitorWin::Observer> device_observer_; base::WeakPtrFactory<HidServiceWin> weak_factory_; |
