Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(95)

Side by Side Diff: device/u2f/u2f_request.cc

Issue 2821263005: Add U2F request state machines (Closed)
Patch Set: Add U2fRequest, U2fSign, and U2fRegister classes Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 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 "u2f_request.h"
6
7 #include "base/bind.h"
8 #include "base/memory/ptr_util.h"
9 #include "base/threading/thread_task_runner_handle.h"
10 #include "device/base/device_client.h"
11 #include "u2f_hid_device.h"
12
13 namespace device {
14
15 U2fRequest::U2fRequest(const ResponseCallback& cb)
16 : state_(State::INIT),
17 cb_(cb),
18 hid_service_observer_(this),
19 weak_factory_(this) {
20 filter_.SetUsagePage(0xf1d0);
21 }
22
23 void U2fRequest::Transition() {
24 switch (state_) {
25 case State::IDLE:
26 IterateDevice();
27 if (!current_device_) {
28 // No devices available
29 state_ = State::OFF;
30 break;
31 }
32 state_ = State::WINK;
33 current_device_->TryWink(
34 base::Bind(&U2fRequest::Transition, weak_factory_.GetWeakPtr()));
35 break;
36 case State::WINK:
37 state_ = State::BUSY;
38 TryDevice();
39 default:
40 break;
41 }
42 }
43
44 void U2fRequest::Start() {
45 if (state_ == State::INIT) {
46 state_ = State::BUSY;
47 Enumerate();
48 }
49 }
50
51 void U2fRequest::Enumerate() {
52 HidService* hid_service = DeviceClient::Get()->GetHidService();
53 DCHECK(hid_service);
54 hid_service_observer_.Add(hid_service);
55 hid_service->GetDevices(
56 base::Bind(&U2fRequest::OnEnumerate, weak_factory_.GetWeakPtr()));
57 }
58
59 void U2fRequest::OnEnumerate(
60 const std::vector<scoped_refptr<HidDeviceInfo>>& devices) {
61 for (auto device_info : devices) {
62 if (filter_.Matches(device_info))
63 devices_.push_back(base::MakeUnique<U2fHidDevice>(device_info));
64 }
65
66 state_ = State::IDLE;
67 Transition();
68 }
69
70 void U2fRequest::OnDeviceAdded(scoped_refptr<HidDeviceInfo> device_info) {
71 // Ignore non-U2F devices
72 if (!filter_.Matches(device_info))
73 return;
74
75 auto device = base::MakeUnique<U2fHidDevice>(device_info);
76 devices_.push_back(std::move(device));
77
78 // Start the state machine if this is the only device
79 if (state_ == State::OFF) {
80 state_ = State::IDLE;
81 delay_callback_.Cancel();
82 Transition();
83 }
84 }
85
86 void U2fRequest::OnDeviceRemoved(scoped_refptr<HidDeviceInfo> device_info) {
87 // Ignore non-U2F devices
88 if (!filter_.Matches(device_info))
89 return;
90
91 auto device = base::MakeUnique<U2fHidDevice>(device_info);
92
93 // Check if the active device was removed
94 if (current_device_ && current_device_->GetId() == device->GetId()) {
95 current_device_ = nullptr;
96 state_ = State::IDLE;
97 Transition();
98 return;
99 }
100
101 // Remove the device if it exists in the devices list
102 for (auto it = devices_.begin(); it != devices_.end();) {
103 if ((*it)->GetId() == device->GetId()) {
104 it = devices_.erase(it);
105 return;
106 } else {
107 ++it;
108 }
109 }
Reilly Grant (use Gerrit) 2017/04/21 17:19:16 devices_.remove_if([](const std::unique_ptr<U2fDev
Casey Piper 2017/04/21 22:55:16 Done.
110
111 // Remove the device if it exists in the attempted devices list
112 for (auto it = attempted_devices_.begin(); it != attempted_devices_.end();) {
113 if ((*it)->GetId() == device->GetId()) {
114 it = attempted_devices_.erase(it);
115 return;
116 } else {
117 ++it;
118 }
119 }
Reilly Grant (use Gerrit) 2017/04/21 17:19:16 attempted_devices_.remove_if( [](const std::un
Casey Piper 2017/04/21 22:55:16 Done.
120 }
121
122 void U2fRequest::IterateDevice() {
123 // Move active device to attempted device list
124 if (current_device_)
125 attempted_devices_.push_back(std::move(current_device_));
126
127 // If there is an additional device on device list, make it active.
128 // Otherwise, if all devices have been tried, move attempted devices back to
129 // the main device list.
130 if (devices_.size() > 0) {
131 current_device_ = std::move(devices_.front());
132 devices_.pop_front();
133 } else if (attempted_devices_.size() > 0) {
134 devices_ = std::move(attempted_devices_);
135 // After trying every device, wait 200ms before trying again
136 delay_callback_.Reset(
137 base::Bind(&U2fRequest::OnWaitComplete, weak_factory_.GetWeakPtr()));
138 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
139 FROM_HERE, delay_callback_.callback(),
140 base::TimeDelta::FromMilliseconds(200));
141 }
142 }
143
144 void U2fRequest::OnWaitComplete() {
145 state_ = State::IDLE;
146 Transition();
147 }
148
149 U2fRequest::~U2fRequest() {}
150
151 } // namespace device
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698