OLD | NEW |
| (Empty) |
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 "chromeos/pairing/fake_controller_pairing_controller.h" | |
6 | |
7 #include <map> | |
8 | |
9 #include "base/bind.h" | |
10 #include "base/logging.h" | |
11 #include "base/message_loop/message_loop.h" | |
12 #include "base/rand_util.h" | |
13 #include "base/strings/string_number_conversions.h" | |
14 #include "base/strings/string_split.h" | |
15 #include "base/strings/string_util.h" | |
16 | |
17 namespace chromeos { | |
18 | |
19 FakeControllerPairingController::FakeControllerPairingController( | |
20 const std::string& config) | |
21 : current_stage_(STAGE_NONE), | |
22 should_fail_on_connecting_(false), | |
23 connection_lost_begin_(STAGE_NONE), | |
24 connection_lost_end_(STAGE_NONE), | |
25 enrollment_should_fail_(false) { | |
26 ApplyConfig(config); | |
27 AddObserver(this); | |
28 } | |
29 | |
30 FakeControllerPairingController::~FakeControllerPairingController() { | |
31 RemoveObserver(this); | |
32 } | |
33 | |
34 void FakeControllerPairingController::ApplyConfig(const std::string& config) { | |
35 typedef std::vector<std::string> Tokens; | |
36 | |
37 base::StringPairs kv_pairs; | |
38 CHECK(base::SplitStringIntoKeyValuePairs(config, ':', ',', &kv_pairs)) | |
39 << "Wrong config format."; | |
40 std::map<std::string, std::string> dict(kv_pairs.begin(), kv_pairs.end()); | |
41 | |
42 if (dict.count("async_duration")) { | |
43 int ms = 0; | |
44 CHECK(base::StringToInt(dict["async_duration"], &ms)) | |
45 << "Wrong 'async_duration' format."; | |
46 async_duration_ = base::TimeDelta::FromMilliseconds(ms); | |
47 } else { | |
48 async_duration_ = base::TimeDelta::FromMilliseconds(3000); | |
49 } | |
50 | |
51 should_fail_on_connecting_ = | |
52 dict.count("fail_connecting") && (dict["fail_connecting"] == "1"); | |
53 | |
54 enrollment_should_fail_ = | |
55 dict.count("fail_enrollment") && (dict["fail_enrollment"] == "1"); | |
56 | |
57 if (dict.count("connection_lost")) { | |
58 Tokens lost_begin_end; | |
59 CHECK(Tokenize(dict["connection_lost"], "-", &lost_begin_end) == 2) | |
60 << "Wrong 'connection_lost' format."; | |
61 int begin = 0; | |
62 int end = 0; | |
63 CHECK(base::StringToInt(lost_begin_end[0], &begin) && | |
64 base::StringToInt(lost_begin_end[1], &end)) | |
65 << "Wrong 'connection_lost' format."; | |
66 CHECK((begin == 0 && end == 0) || | |
67 (STAGE_WAITING_FOR_CODE_CONFIRMATION <= begin && begin <= end && | |
68 end <= STAGE_HOST_ENROLLMENT_ERROR)) | |
69 << "Wrong 'connection_lost' interval."; | |
70 connection_lost_begin_ = static_cast<Stage>(begin); | |
71 connection_lost_end_ = static_cast<Stage>(end); | |
72 } else { | |
73 connection_lost_begin_ = connection_lost_end_ = STAGE_NONE; | |
74 } | |
75 | |
76 if (!dict.count("discovery")) { | |
77 dict["discovery"] = | |
78 "F-Device_1~F-Device_5~F-Device_3~L-Device_3~L-Device_1~F-Device_1"; | |
79 } | |
80 base::StringPairs events; | |
81 CHECK( | |
82 base::SplitStringIntoKeyValuePairs(dict["discovery"], '-', '~', &events)) | |
83 << "Wrong 'discovery' format."; | |
84 DiscoveryScenario scenario; | |
85 for (base::StringPairs::const_iterator event = events.begin(); | |
86 event != events.end(); | |
87 ++event) { | |
88 std::string type = event->first; | |
89 std::string device_id = event->second; | |
90 CHECK(type == "F" || type == "L" || type == "N") | |
91 << "Wrong discovery event type."; | |
92 CHECK(!device_id.empty() || type == "N") << "Empty device ID."; | |
93 scenario.push_back(DiscoveryEvent( | |
94 type == "F" ? DEVICE_FOUND : type == "L" ? DEVICE_LOST : NOTHING_FOUND, | |
95 device_id)); | |
96 } | |
97 SetDiscoveryScenario(scenario); | |
98 | |
99 preset_confirmation_code_ = dict["code"]; | |
100 CHECK(preset_confirmation_code_.empty() || | |
101 (preset_confirmation_code_.length() == 6 && | |
102 preset_confirmation_code_.find_first_not_of("0123456789") == | |
103 std::string::npos)) | |
104 << "Wrong 'code' format."; | |
105 } | |
106 | |
107 void FakeControllerPairingController::SetShouldFailOnConnecting() { | |
108 should_fail_on_connecting_ = true; | |
109 } | |
110 | |
111 void FakeControllerPairingController::SetShouldLoseConnection(Stage stage_begin, | |
112 Stage stage_end) { | |
113 connection_lost_begin_ = stage_begin; | |
114 connection_lost_end_ = stage_end; | |
115 } | |
116 | |
117 void FakeControllerPairingController::SetEnrollmentShouldFail() { | |
118 enrollment_should_fail_ = true; | |
119 } | |
120 | |
121 void FakeControllerPairingController::SetDiscoveryScenario( | |
122 const DiscoveryScenario& discovery_scenario) { | |
123 discovery_scenario_ = discovery_scenario; | |
124 // Check that scenario is valid. | |
125 std::set<std::string> devices; | |
126 for (DiscoveryScenario::const_iterator event = discovery_scenario_.begin(); | |
127 event != discovery_scenario_.end(); | |
128 ++event) { | |
129 switch (event->first) { | |
130 case DEVICE_FOUND: { | |
131 devices.insert(event->second); | |
132 break; | |
133 } | |
134 case DEVICE_LOST: { | |
135 CHECK(devices.count(event->second)); | |
136 devices.erase(event->second); | |
137 break; | |
138 } | |
139 case NOTHING_FOUND: { | |
140 CHECK(++event == discovery_scenario_.end()); | |
141 return; | |
142 } | |
143 } | |
144 } | |
145 } | |
146 | |
147 void FakeControllerPairingController::AddObserver(Observer* observer) { | |
148 observers_.AddObserver(observer); | |
149 } | |
150 | |
151 void FakeControllerPairingController::RemoveObserver(Observer* observer) { | |
152 observers_.RemoveObserver(observer); | |
153 } | |
154 | |
155 ControllerPairingController::Stage | |
156 FakeControllerPairingController::GetCurrentStage() { | |
157 return current_stage_; | |
158 } | |
159 | |
160 void FakeControllerPairingController::StartPairing() { | |
161 CHECK(current_stage_ == STAGE_NONE); | |
162 ChangeStage(STAGE_DEVICES_DISCOVERY); | |
163 } | |
164 | |
165 ControllerPairingController::DeviceIdList | |
166 FakeControllerPairingController::GetDiscoveredDevices() { | |
167 CHECK(current_stage_ == STAGE_DEVICES_DISCOVERY); | |
168 return DeviceIdList(discovered_devices_.begin(), discovered_devices_.end()); | |
169 } | |
170 | |
171 void FakeControllerPairingController::ChooseDeviceForPairing( | |
172 const std::string& device_id) { | |
173 CHECK(current_stage_ == STAGE_DEVICES_DISCOVERY); | |
174 CHECK(discovered_devices_.count(device_id)); | |
175 choosen_device_ = device_id; | |
176 ChangeStage(STAGE_ESTABLISHING_CONNECTION); | |
177 } | |
178 | |
179 void FakeControllerPairingController::RepeatDiscovery() { | |
180 CHECK(current_stage_ == STAGE_DEVICE_NOT_FOUND || | |
181 current_stage_ == STAGE_ESTABLISHING_CONNECTION_ERROR || | |
182 current_stage_ == STAGE_HOST_ENROLLMENT_ERROR); | |
183 ChangeStage(STAGE_DEVICES_DISCOVERY); | |
184 } | |
185 | |
186 std::string FakeControllerPairingController::GetConfirmationCode() { | |
187 CHECK(current_stage_ == STAGE_WAITING_FOR_CODE_CONFIRMATION); | |
188 if (confirmation_code_.empty()) { | |
189 if (preset_confirmation_code_.empty()) { | |
190 for (int i = 0; i < 6; ++i) | |
191 confirmation_code_.push_back(base::RandInt('0', '9')); | |
192 } else { | |
193 confirmation_code_ = preset_confirmation_code_; | |
194 } | |
195 } | |
196 return confirmation_code_; | |
197 } | |
198 | |
199 void FakeControllerPairingController::SetConfirmationCodeIsCorrect( | |
200 bool correct) { | |
201 CHECK(current_stage_ == STAGE_WAITING_FOR_CODE_CONFIRMATION); | |
202 if (correct) | |
203 ChangeStage(STAGE_HOST_UPDATE_IN_PROGRESS); | |
204 else | |
205 ChangeStage(STAGE_DEVICES_DISCOVERY); | |
206 } | |
207 | |
208 void FakeControllerPairingController::OnAuthenticationDone( | |
209 const chromeos::UserContext& user_context, | |
210 content::BrowserContext* browser_context) { | |
211 CHECK(current_stage_ == STAGE_WAITING_FOR_CREDENTIALS); | |
212 ChangeStage(STAGE_HOST_ENROLLMENT_IN_PROGRESS); | |
213 } | |
214 | |
215 void FakeControllerPairingController::StartSession() { | |
216 CHECK(current_stage_ == STAGE_PAIRING_DONE); | |
217 ChangeStage(STAGE_FINISHED); | |
218 } | |
219 | |
220 void FakeControllerPairingController::ChangeStage(Stage new_stage) { | |
221 if (current_stage_ == new_stage) | |
222 return; | |
223 current_stage_ = new_stage; | |
224 FOR_EACH_OBSERVER(Observer, observers_, PairingStageChanged(new_stage)); | |
225 } | |
226 | |
227 void FakeControllerPairingController::ChangeStageLater(Stage new_stage) { | |
228 base::MessageLoop::current()->PostDelayedTask( | |
229 FROM_HERE, | |
230 base::Bind(&FakeControllerPairingController::ChangeStage, | |
231 base::Unretained(this), | |
232 new_stage), | |
233 async_duration_); | |
234 } | |
235 | |
236 void FakeControllerPairingController::ExecuteDiscoveryEvent( | |
237 size_t event_position) { | |
238 if (current_stage_ != STAGE_DEVICES_DISCOVERY) | |
239 return; | |
240 CHECK(event_position < discovery_scenario_.size()); | |
241 const DiscoveryEvent& event = discovery_scenario_[event_position]; | |
242 switch (event.first) { | |
243 case DEVICE_FOUND: { | |
244 DeviceFound(event.second); | |
245 break; | |
246 } | |
247 case DEVICE_LOST: { | |
248 DeviceLost(event.second); | |
249 break; | |
250 } | |
251 case NOTHING_FOUND: { | |
252 ChangeStage(STAGE_DEVICE_NOT_FOUND); | |
253 break; | |
254 } | |
255 } | |
256 if (++event_position == discovery_scenario_.size()) { | |
257 return; | |
258 } | |
259 base::MessageLoop::current()->PostDelayedTask( | |
260 FROM_HERE, | |
261 base::Bind(&FakeControllerPairingController::ExecuteDiscoveryEvent, | |
262 base::Unretained(this), | |
263 event_position), | |
264 async_duration_); | |
265 } | |
266 | |
267 void FakeControllerPairingController::DeviceFound( | |
268 const std::string& device_id) { | |
269 CHECK(current_stage_ == STAGE_DEVICES_DISCOVERY); | |
270 discovered_devices_.insert(device_id); | |
271 FOR_EACH_OBSERVER(Observer, observers_, DiscoveredDevicesListChanged()); | |
272 } | |
273 | |
274 void FakeControllerPairingController::DeviceLost(const std::string& device_id) { | |
275 CHECK(current_stage_ == STAGE_DEVICES_DISCOVERY); | |
276 discovered_devices_.erase(device_id); | |
277 FOR_EACH_OBSERVER(Observer, observers_, DiscoveredDevicesListChanged()); | |
278 } | |
279 | |
280 void FakeControllerPairingController::PairingStageChanged(Stage new_stage) { | |
281 Stage next_stage = STAGE_NONE; | |
282 switch (new_stage) { | |
283 case STAGE_DEVICES_DISCOVERY: { | |
284 discovered_devices_.clear(); | |
285 base::MessageLoop::current()->PostDelayedTask( | |
286 FROM_HERE, | |
287 base::Bind(&FakeControllerPairingController::ExecuteDiscoveryEvent, | |
288 base::Unretained(this), | |
289 0), | |
290 async_duration_); | |
291 break; | |
292 } | |
293 case STAGE_ESTABLISHING_CONNECTION: { | |
294 if (should_fail_on_connecting_) { | |
295 next_stage = STAGE_ESTABLISHING_CONNECTION_ERROR; | |
296 should_fail_on_connecting_ = false; | |
297 } else { | |
298 confirmation_code_.clear(); | |
299 next_stage = STAGE_WAITING_FOR_CODE_CONFIRMATION; | |
300 } | |
301 break; | |
302 } | |
303 case STAGE_HOST_UPDATE_IN_PROGRESS: { | |
304 next_stage = STAGE_WAITING_FOR_CREDENTIALS; | |
305 break; | |
306 } | |
307 case STAGE_HOST_ENROLLMENT_IN_PROGRESS: { | |
308 if (enrollment_should_fail_) { | |
309 enrollment_should_fail_ = false; | |
310 next_stage = STAGE_HOST_ENROLLMENT_ERROR; | |
311 } else { | |
312 next_stage = STAGE_PAIRING_DONE; | |
313 } | |
314 break; | |
315 } | |
316 case STAGE_HOST_CONNECTION_LOST: { | |
317 next_stage = connection_lost_end_; | |
318 connection_lost_end_ = STAGE_NONE; | |
319 break; | |
320 } | |
321 default: | |
322 break; | |
323 } | |
324 if (new_stage == connection_lost_begin_) { | |
325 connection_lost_begin_ = STAGE_NONE; | |
326 next_stage = STAGE_HOST_CONNECTION_LOST; | |
327 } | |
328 if (next_stage != STAGE_NONE) | |
329 ChangeStageLater(next_stage); | |
330 } | |
331 | |
332 void FakeControllerPairingController::DiscoveredDevicesListChanged() { | |
333 } | |
334 | |
335 } // namespace chromeos | |
OLD | NEW |