Chromium Code Reviews| Index: device/u2f/u2f_hid_device.cc |
| diff --git a/device/u2f/u2f_hid_device.cc b/device/u2f/u2f_hid_device.cc |
| index c313b96e4c165aab270e68e616c552fa4401d62c..1c50f877797ea59a64d1f360f2e2cea79f3fdece 100644 |
| --- a/device/u2f/u2f_hid_device.cc |
| +++ b/device/u2f/u2f_hid_device.cc |
| @@ -7,6 +7,7 @@ |
| #include "base/bind.h" |
| #include "base/bind_helpers.h" |
| #include "base/command_line.h" |
| +#include "base/threading/thread_task_runner_handle.h" |
| #include "crypto/random.h" |
| #include "device/base/device_client.h" |
| #include "device/hid/hid_connection.h" |
| @@ -29,7 +30,7 @@ U2fHidDevice::U2fHidDevice(scoped_refptr<HidDeviceInfo> device_info) |
| U2fHidDevice::~U2fHidDevice() { |
| // Cleanup connection |
| - if (connection_) |
| + if (connection_ && !connection_->closed()) |
| connection_->Close(); |
| } |
| @@ -41,22 +42,54 @@ void U2fHidDevice::DeviceTransact(std::unique_ptr<U2fApduCommand> command, |
| void U2fHidDevice::Transition(std::unique_ptr<U2fApduCommand> command, |
| const DeviceCallback& callback) { |
| switch (state_) { |
| - case State::INIT: |
| + case State::INIT: { |
| state_ = State::BUSY; |
| + timeout_callback_.Reset(base::Bind(&U2fHidDevice::OnTimeout, |
| + weak_factory_.GetWeakPtr(), callback)); |
| + auto self = weak_factory_.GetWeakPtr(); |
| Connect(base::Bind(&U2fHidDevice::OnConnect, weak_factory_.GetWeakPtr(), |
| base::Passed(&command), callback)); |
| + if (self && !timeout_callback_.IsCancelled()) { |
| + // Setup timeout task for 3 seconds |
|
Reilly Grant (use Gerrit)
2017/04/17 22:25:17
Set up the timeout task before calling Connect to
Casey Piper
2017/04/17 23:02:38
Done. Did you mean DCHECK(timeout_callback.IsCance
|
| + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| + FROM_HERE, timeout_callback_.callback(), |
| + base::TimeDelta::FromMilliseconds(3000)); |
| + } |
| break; |
| - case State::CONNECTED: |
| + } |
| + case State::CONNECTED: { |
| state_ = State::BUSY; |
| + timeout_callback_.Reset(base::Bind(&U2fHidDevice::OnTimeout, |
| + weak_factory_.GetWeakPtr(), callback)); |
| + auto self = weak_factory_.GetWeakPtr(); |
| AllocateChannel(std::move(command), callback); |
| + if (self && !timeout_callback_.IsCancelled()) { |
| + // Setup timeout task for 3 seconds |
| + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| + FROM_HERE, timeout_callback_.callback(), |
| + base::TimeDelta::FromMilliseconds(3000)); |
| + } |
| break; |
| + } |
| case State::IDLE: { |
| state_ = State::BUSY; |
| std::unique_ptr<U2fMessage> msg = U2fMessage::Create( |
| channel_id_, U2fMessage::Type::CMD_MSG, command->GetEncodedCommand()); |
| + |
| + timeout_callback_.Reset(base::Bind(&U2fHidDevice::OnTimeout, |
| + weak_factory_.GetWeakPtr(), callback)); |
| + auto self = weak_factory_.GetWeakPtr(); |
| + // Write message to the device |
| WriteMessage(std::move(msg), true, |
| base::Bind(&U2fHidDevice::MessageReceived, |
| weak_factory_.GetWeakPtr(), callback)); |
| + |
| + if (self && !timeout_callback_.IsCancelled()) { |
| + // Setup timeout task for 3 seconds |
| + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| + FROM_HERE, timeout_callback_.callback(), |
| + base::TimeDelta::FromMilliseconds(3000)); |
| + } |
| break; |
| } |
| case State::BUSY: |
| @@ -86,6 +119,11 @@ void U2fHidDevice::Connect(const HidService::ConnectCallback& callback) { |
| void U2fHidDevice::OnConnect(std::unique_ptr<U2fApduCommand> command, |
| const DeviceCallback& callback, |
| scoped_refptr<HidConnection> connection) { |
| + if (timeout_callback_.IsCancelled()) { |
| + return; |
| + } |
|
Reilly Grant (use Gerrit)
2017/04/17 22:25:17
nit: no braces around single-line if.
The state m
Casey Piper
2017/04/17 23:02:38
Done.
|
| + timeout_callback_.Cancel(); |
| + |
| if (connection) { |
| connection_ = connection; |
| state_ = State::CONNECTED; |
| @@ -114,6 +152,11 @@ void U2fHidDevice::OnAllocateChannel(std::vector<uint8_t> nonce, |
| const DeviceCallback& callback, |
| bool success, |
| std::unique_ptr<U2fMessage> message) { |
| + if (timeout_callback_.IsCancelled()) { |
| + return; |
| + } |
|
Reilly Grant (use Gerrit)
2017/04/17 22:25:17
nit: no braces around single-line if.
Casey Piper
2017/04/17 23:02:38
Done.
|
| + timeout_callback_.Cancel(); |
| + |
| if (!success || !message) { |
| state_ = State::DEVICE_ERROR; |
| Transition(nullptr, callback); |
| @@ -213,9 +256,10 @@ void U2fHidDevice::OnRead(U2fHidMessageCallback callback, |
| // Received a message from a different channel, so try again |
| if (channel_id_ != read_message->channel_id()) { |
| - connection_->Read(base::Bind(&U2fHidDevice::OnRead, |
| - weak_factory_.GetWeakPtr(), |
| - base::Passed(&callback))); |
| + base::ThreadTaskRunnerHandle::Get()->PostTask( |
| + FROM_HERE, |
| + base::Bind(&U2fHidDevice::ReadMessage, weak_factory_.GetWeakPtr(), |
| + base::Passed(&callback))); |
| return; |
| } |
| @@ -251,14 +295,20 @@ void U2fHidDevice::OnReadContinuation(std::unique_ptr<U2fMessage> message, |
| base::Passed(&message), base::Passed(&callback))); |
| } |
| -void U2fHidDevice::MessageReceived(const DeviceCallback& callback, |
| +void U2fHidDevice::MessageReceived(DeviceCallback callback, |
| bool success, |
| std::unique_ptr<U2fMessage> message) { |
| + if (timeout_callback_.IsCancelled()) { |
| + return; |
| + } |
|
Reilly Grant (use Gerrit)
2017/04/17 22:25:17
nit: no braces around single-line if.
Casey Piper
2017/04/17 23:02:38
Done.
|
| + timeout_callback_.Cancel(); |
| + |
| if (!success) { |
| state_ = State::DEVICE_ERROR; |
| Transition(nullptr, callback); |
| return; |
| } |
| + |
| std::unique_ptr<U2fApduResponse> response = nullptr; |
| if (message) |
| response = U2fApduResponse::CreateFromMessage(message->GetMessagePayload()); |
| @@ -297,8 +347,14 @@ void U2fHidDevice::OnWink(const WinkCallback& callback, |
| callback.Run(); |
| } |
| +void U2fHidDevice::OnTimeout(DeviceCallback callback) { |
| + timeout_callback_.Cancel(); |
|
Reilly Grant (use Gerrit)
2017/04/17 22:25:17
Since timeout_callback_ can only fire once it shou
Casey Piper
2017/04/17 23:02:38
Done.
|
| + state_ = State::DEVICE_ERROR; |
| + Transition(nullptr, callback); |
| +} |
| + |
| std::string U2fHidDevice::GetId() { |
| - std::ostringstream id("hid:"); |
| + std::ostringstream id("hid:", std::ios::ate); |
| id << device_info_->device_id(); |
| return id.str(); |
| } |