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(); |
} |