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.
5 #include "components/pairing/fake_controller_pairing_controller.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"
17 namespace pairing_chromeos
{
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) {
30 FakeControllerPairingController::~FakeControllerPairingController() {
34 void FakeControllerPairingController::ApplyConfig(const std::string
& config
) {
35 typedef std::vector
<std::string
> Tokens
;
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());
42 if (dict
.count("async_duration")) {
44 CHECK(base::StringToInt(dict
["async_duration"], &ms
))
45 << "Wrong 'async_duration' format.";
46 async_duration_
= base::TimeDelta::FromMilliseconds(ms
);
48 async_duration_
= base::TimeDelta::FromMilliseconds(3000);
51 should_fail_on_connecting_
=
52 dict
.count("fail_connecting") && (dict
["fail_connecting"] == "1");
54 enrollment_should_fail_
=
55 dict
.count("fail_enrollment") && (dict
["fail_enrollment"] == "1");
57 if (dict
.count("connection_lost")) {
58 Tokens lost_begin_end
= base::SplitString(
59 dict
["connection_lost"], "-", base::KEEP_WHITESPACE
,
60 base::SPLIT_WANT_NONEMPTY
);
61 CHECK_EQ(2u, lost_begin_end
.size()) << "Wrong 'connection_lost' format.";
64 CHECK(base::StringToInt(lost_begin_end
[0], &begin
) &&
65 base::StringToInt(lost_begin_end
[1], &end
))
66 << "Wrong 'connection_lost' format.";
67 CHECK((begin
== 0 && end
== 0) ||
68 (STAGE_WAITING_FOR_CODE_CONFIRMATION
<= begin
&& begin
<= end
&&
69 end
<= STAGE_HOST_ENROLLMENT_ERROR
))
70 << "Wrong 'connection_lost' interval.";
71 connection_lost_begin_
= static_cast<Stage
>(begin
);
72 connection_lost_end_
= static_cast<Stage
>(end
);
74 connection_lost_begin_
= connection_lost_end_
= STAGE_NONE
;
77 if (!dict
.count("discovery")) {
79 "F-Device_1~F-Device_5~F-Device_3~L-Device_3~L-Device_1~F-Device_1";
81 base::StringPairs events
;
83 base::SplitStringIntoKeyValuePairs(dict
["discovery"], '-', '~', &events
))
84 << "Wrong 'discovery' format.";
85 DiscoveryScenario scenario
;
86 for (const auto& event
: events
) {
87 const std::string
& type
= event
.first
;
88 const std::string
& device_id
= event
.second
;
89 CHECK(type
== "F" || type
== "L" || type
== "N")
90 << "Wrong discovery event type.";
91 CHECK(!device_id
.empty() || type
== "N") << "Empty device ID.";
92 scenario
.push_back(DiscoveryEvent(
93 type
== "F" ? DEVICE_FOUND
: type
== "L" ? DEVICE_LOST
: NOTHING_FOUND
,
96 SetDiscoveryScenario(scenario
);
98 preset_confirmation_code_
= dict
["code"];
99 CHECK(preset_confirmation_code_
.empty() ||
100 (preset_confirmation_code_
.length() == 6 &&
101 preset_confirmation_code_
.find_first_not_of("0123456789") ==
103 << "Wrong 'code' format.";
106 void FakeControllerPairingController::SetShouldFailOnConnecting() {
107 should_fail_on_connecting_
= true;
110 void FakeControllerPairingController::SetShouldLoseConnection(Stage stage_begin
,
112 connection_lost_begin_
= stage_begin
;
113 connection_lost_end_
= stage_end
;
116 void FakeControllerPairingController::SetEnrollmentShouldFail() {
117 enrollment_should_fail_
= true;
120 void FakeControllerPairingController::SetDiscoveryScenario(
121 const DiscoveryScenario
& discovery_scenario
) {
122 discovery_scenario_
= discovery_scenario
;
123 // Check that scenario is valid.
124 std::set
<std::string
> devices
;
125 for (DiscoveryScenario::const_iterator event
= discovery_scenario_
.begin();
126 event
!= discovery_scenario_
.end();
128 switch (event
->first
) {
130 devices
.insert(event
->second
);
134 CHECK(devices
.count(event
->second
));
135 devices
.erase(event
->second
);
138 case NOTHING_FOUND
: {
139 CHECK(++event
== discovery_scenario_
.end());
146 void FakeControllerPairingController::AddObserver(Observer
* observer
) {
147 observers_
.AddObserver(observer
);
150 void FakeControllerPairingController::RemoveObserver(Observer
* observer
) {
151 observers_
.RemoveObserver(observer
);
154 ControllerPairingController::Stage
155 FakeControllerPairingController::GetCurrentStage() {
156 return current_stage_
;
159 void FakeControllerPairingController::StartPairing() {
160 CHECK(current_stage_
== STAGE_NONE
);
161 ChangeStage(STAGE_DEVICES_DISCOVERY
);
164 ControllerPairingController::DeviceIdList
165 FakeControllerPairingController::GetDiscoveredDevices() {
166 CHECK(current_stage_
== STAGE_DEVICES_DISCOVERY
);
167 return DeviceIdList(discovered_devices_
.begin(), discovered_devices_
.end());
170 void FakeControllerPairingController::ChooseDeviceForPairing(
171 const std::string
& device_id
) {
172 CHECK(current_stage_
== STAGE_DEVICES_DISCOVERY
);
173 CHECK(discovered_devices_
.count(device_id
));
174 choosen_device_
= device_id
;
175 ChangeStage(STAGE_ESTABLISHING_CONNECTION
);
178 void FakeControllerPairingController::RepeatDiscovery() {
179 CHECK(current_stage_
== STAGE_DEVICE_NOT_FOUND
||
180 current_stage_
== STAGE_ESTABLISHING_CONNECTION_ERROR
||
181 current_stage_
== STAGE_HOST_ENROLLMENT_ERROR
);
182 ChangeStage(STAGE_DEVICES_DISCOVERY
);
185 std::string
FakeControllerPairingController::GetConfirmationCode() {
186 CHECK(current_stage_
== STAGE_WAITING_FOR_CODE_CONFIRMATION
);
187 if (confirmation_code_
.empty()) {
188 if (preset_confirmation_code_
.empty()) {
189 for (int i
= 0; i
< 6; ++i
)
190 confirmation_code_
.push_back(base::RandInt('0', '9'));
192 confirmation_code_
= preset_confirmation_code_
;
195 return confirmation_code_
;
198 void FakeControllerPairingController::SetConfirmationCodeIsCorrect(
200 CHECK(current_stage_
== STAGE_WAITING_FOR_CODE_CONFIRMATION
);
202 ChangeStage(STAGE_HOST_UPDATE_IN_PROGRESS
);
204 ChangeStage(STAGE_DEVICES_DISCOVERY
);
207 void FakeControllerPairingController::SetHostConfiguration(
209 const std::string
& lang
,
210 const std::string
& timezone
,
212 const std::string
& keyboard_layout
) {
215 void FakeControllerPairingController::OnAuthenticationDone(
216 const std::string
& domain
,
217 const std::string
& auth_token
) {
218 CHECK(current_stage_
== STAGE_WAITING_FOR_CREDENTIALS
);
219 ChangeStage(STAGE_HOST_ENROLLMENT_IN_PROGRESS
);
222 void FakeControllerPairingController::StartSession() {
223 CHECK(current_stage_
== STAGE_HOST_ENROLLMENT_SUCCESS
);
224 ChangeStage(STAGE_FINISHED
);
227 void FakeControllerPairingController::ChangeStage(Stage new_stage
) {
228 if (current_stage_
== new_stage
)
230 current_stage_
= new_stage
;
231 FOR_EACH_OBSERVER(Observer
, observers_
, PairingStageChanged(new_stage
));
234 void FakeControllerPairingController::ChangeStageLater(Stage new_stage
) {
235 base::MessageLoop::current()->PostDelayedTask(
237 base::Bind(&FakeControllerPairingController::ChangeStage
,
238 base::Unretained(this),
243 void FakeControllerPairingController::ExecuteDiscoveryEvent(
244 size_t event_position
) {
245 if (current_stage_
!= STAGE_DEVICES_DISCOVERY
)
247 CHECK(event_position
< discovery_scenario_
.size());
248 const DiscoveryEvent
& event
= discovery_scenario_
[event_position
];
249 switch (event
.first
) {
251 DeviceFound(event
.second
);
255 DeviceLost(event
.second
);
258 case NOTHING_FOUND
: {
259 ChangeStage(STAGE_DEVICE_NOT_FOUND
);
263 if (++event_position
== discovery_scenario_
.size()) {
266 base::MessageLoop::current()->PostDelayedTask(
268 base::Bind(&FakeControllerPairingController::ExecuteDiscoveryEvent
,
269 base::Unretained(this),
274 void FakeControllerPairingController::DeviceFound(
275 const std::string
& device_id
) {
276 CHECK(current_stage_
== STAGE_DEVICES_DISCOVERY
);
277 discovered_devices_
.insert(device_id
);
278 FOR_EACH_OBSERVER(Observer
, observers_
, DiscoveredDevicesListChanged());
281 void FakeControllerPairingController::DeviceLost(const std::string
& device_id
) {
282 CHECK(current_stage_
== STAGE_DEVICES_DISCOVERY
);
283 discovered_devices_
.erase(device_id
);
284 FOR_EACH_OBSERVER(Observer
, observers_
, DiscoveredDevicesListChanged());
287 void FakeControllerPairingController::PairingStageChanged(Stage new_stage
) {
288 Stage next_stage
= STAGE_NONE
;
290 case STAGE_DEVICES_DISCOVERY
: {
291 discovered_devices_
.clear();
292 base::MessageLoop::current()->PostDelayedTask(
294 base::Bind(&FakeControllerPairingController::ExecuteDiscoveryEvent
,
295 base::Unretained(this),
300 case STAGE_ESTABLISHING_CONNECTION
: {
301 if (should_fail_on_connecting_
) {
302 next_stage
= STAGE_ESTABLISHING_CONNECTION_ERROR
;
303 should_fail_on_connecting_
= false;
305 confirmation_code_
.clear();
306 next_stage
= STAGE_WAITING_FOR_CODE_CONFIRMATION
;
310 case STAGE_HOST_UPDATE_IN_PROGRESS
: {
311 next_stage
= STAGE_WAITING_FOR_CREDENTIALS
;
314 case STAGE_HOST_ENROLLMENT_IN_PROGRESS
: {
315 if (enrollment_should_fail_
) {
316 enrollment_should_fail_
= false;
317 next_stage
= STAGE_HOST_ENROLLMENT_ERROR
;
319 next_stage
= STAGE_HOST_ENROLLMENT_SUCCESS
;
323 case STAGE_HOST_CONNECTION_LOST
: {
324 next_stage
= connection_lost_end_
;
325 connection_lost_end_
= STAGE_NONE
;
331 if (new_stage
== connection_lost_begin_
) {
332 connection_lost_begin_
= STAGE_NONE
;
333 next_stage
= STAGE_HOST_CONNECTION_LOST
;
335 if (next_stage
!= STAGE_NONE
)
336 ChangeStageLater(next_stage
);
339 void FakeControllerPairingController::DiscoveredDevicesListChanged() {
342 } // namespace pairing_chromeos