Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / components / pairing / fake_controller_pairing_controller.cc
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 "components/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 pairing_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 (const auto& event : events) {
86     const std::string& type = event.first;
87     const std::string& device_id = event.second;
88     CHECK(type == "F" || type == "L" || type == "N")
89         << "Wrong discovery event type.";
90     CHECK(!device_id.empty() || type == "N") << "Empty device ID.";
91     scenario.push_back(DiscoveryEvent(
92         type == "F" ? DEVICE_FOUND : type == "L" ? DEVICE_LOST : NOTHING_FOUND,
93         device_id));
94   }
95   SetDiscoveryScenario(scenario);
96
97   preset_confirmation_code_ = dict["code"];
98   CHECK(preset_confirmation_code_.empty() ||
99         (preset_confirmation_code_.length() == 6 &&
100          preset_confirmation_code_.find_first_not_of("0123456789") ==
101              std::string::npos))
102       << "Wrong 'code' format.";
103 }
104
105 void FakeControllerPairingController::SetShouldFailOnConnecting() {
106   should_fail_on_connecting_ = true;
107 }
108
109 void FakeControllerPairingController::SetShouldLoseConnection(Stage stage_begin,
110                                                               Stage stage_end) {
111   connection_lost_begin_ = stage_begin;
112   connection_lost_end_ = stage_end;
113 }
114
115 void FakeControllerPairingController::SetEnrollmentShouldFail() {
116   enrollment_should_fail_ = true;
117 }
118
119 void FakeControllerPairingController::SetDiscoveryScenario(
120     const DiscoveryScenario& discovery_scenario) {
121   discovery_scenario_ = discovery_scenario;
122   // Check that scenario is valid.
123   std::set<std::string> devices;
124   for (DiscoveryScenario::const_iterator event = discovery_scenario_.begin();
125        event != discovery_scenario_.end();
126        ++event) {
127     switch (event->first) {
128       case DEVICE_FOUND: {
129         devices.insert(event->second);
130         break;
131       }
132       case DEVICE_LOST: {
133         CHECK(devices.count(event->second));
134         devices.erase(event->second);
135         break;
136       }
137       case NOTHING_FOUND: {
138         CHECK(++event == discovery_scenario_.end());
139         return;
140       }
141     }
142   }
143 }
144
145 void FakeControllerPairingController::AddObserver(Observer* observer) {
146   observers_.AddObserver(observer);
147 }
148
149 void FakeControllerPairingController::RemoveObserver(Observer* observer) {
150   observers_.RemoveObserver(observer);
151 }
152
153 ControllerPairingController::Stage
154 FakeControllerPairingController::GetCurrentStage() {
155   return current_stage_;
156 }
157
158 void FakeControllerPairingController::StartPairing() {
159   CHECK(current_stage_ == STAGE_NONE);
160   ChangeStage(STAGE_DEVICES_DISCOVERY);
161 }
162
163 ControllerPairingController::DeviceIdList
164 FakeControllerPairingController::GetDiscoveredDevices() {
165   CHECK(current_stage_ == STAGE_DEVICES_DISCOVERY);
166   return DeviceIdList(discovered_devices_.begin(), discovered_devices_.end());
167 }
168
169 void FakeControllerPairingController::ChooseDeviceForPairing(
170     const std::string& device_id) {
171   CHECK(current_stage_ == STAGE_DEVICES_DISCOVERY);
172   CHECK(discovered_devices_.count(device_id));
173   choosen_device_ = device_id;
174   ChangeStage(STAGE_ESTABLISHING_CONNECTION);
175 }
176
177 void FakeControllerPairingController::RepeatDiscovery() {
178   CHECK(current_stage_ == STAGE_DEVICE_NOT_FOUND ||
179         current_stage_ == STAGE_ESTABLISHING_CONNECTION_ERROR ||
180         current_stage_ == STAGE_HOST_ENROLLMENT_ERROR);
181   ChangeStage(STAGE_DEVICES_DISCOVERY);
182 }
183
184 std::string FakeControllerPairingController::GetConfirmationCode() {
185   CHECK(current_stage_ == STAGE_WAITING_FOR_CODE_CONFIRMATION);
186   if (confirmation_code_.empty()) {
187     if (preset_confirmation_code_.empty()) {
188       for (int i = 0; i < 6; ++i)
189         confirmation_code_.push_back(base::RandInt('0', '9'));
190     } else {
191       confirmation_code_ = preset_confirmation_code_;
192     }
193   }
194   return confirmation_code_;
195 }
196
197 void FakeControllerPairingController::SetConfirmationCodeIsCorrect(
198     bool correct) {
199   CHECK(current_stage_ == STAGE_WAITING_FOR_CODE_CONFIRMATION);
200   if (correct)
201     ChangeStage(STAGE_HOST_UPDATE_IN_PROGRESS);
202   else
203     ChangeStage(STAGE_DEVICES_DISCOVERY);
204 }
205
206 void FakeControllerPairingController::SetHostConfiguration(
207     bool accepted_eula,
208     const std::string& lang,
209     const std::string& timezone,
210     bool send_reports,
211     const std::string& keyboard_layout) {
212 }
213
214 void FakeControllerPairingController::OnAuthenticationDone(
215     const std::string& domain,
216     const std::string& auth_token) {
217   CHECK(current_stage_ == STAGE_WAITING_FOR_CREDENTIALS);
218   ChangeStage(STAGE_HOST_ENROLLMENT_IN_PROGRESS);
219 }
220
221 void FakeControllerPairingController::StartSession() {
222   CHECK(current_stage_ == STAGE_HOST_ENROLLMENT_SUCCESS);
223   ChangeStage(STAGE_FINISHED);
224 }
225
226 void FakeControllerPairingController::ChangeStage(Stage new_stage) {
227   if (current_stage_ == new_stage)
228     return;
229   current_stage_ = new_stage;
230   FOR_EACH_OBSERVER(Observer, observers_, PairingStageChanged(new_stage));
231 }
232
233 void FakeControllerPairingController::ChangeStageLater(Stage new_stage) {
234   base::MessageLoop::current()->PostDelayedTask(
235       FROM_HERE,
236       base::Bind(&FakeControllerPairingController::ChangeStage,
237                  base::Unretained(this),
238                  new_stage),
239       async_duration_);
240 }
241
242 void FakeControllerPairingController::ExecuteDiscoveryEvent(
243     size_t event_position) {
244   if (current_stage_ != STAGE_DEVICES_DISCOVERY)
245     return;
246   CHECK(event_position < discovery_scenario_.size());
247   const DiscoveryEvent& event = discovery_scenario_[event_position];
248   switch (event.first) {
249     case DEVICE_FOUND: {
250       DeviceFound(event.second);
251       break;
252     }
253     case DEVICE_LOST: {
254       DeviceLost(event.second);
255       break;
256     }
257     case NOTHING_FOUND: {
258       ChangeStage(STAGE_DEVICE_NOT_FOUND);
259       break;
260     }
261   }
262   if (++event_position == discovery_scenario_.size()) {
263     return;
264   }
265   base::MessageLoop::current()->PostDelayedTask(
266       FROM_HERE,
267       base::Bind(&FakeControllerPairingController::ExecuteDiscoveryEvent,
268                  base::Unretained(this),
269                  event_position),
270       async_duration_);
271 }
272
273 void FakeControllerPairingController::DeviceFound(
274     const std::string& device_id) {
275   CHECK(current_stage_ == STAGE_DEVICES_DISCOVERY);
276   discovered_devices_.insert(device_id);
277   FOR_EACH_OBSERVER(Observer, observers_, DiscoveredDevicesListChanged());
278 }
279
280 void FakeControllerPairingController::DeviceLost(const std::string& device_id) {
281   CHECK(current_stage_ == STAGE_DEVICES_DISCOVERY);
282   discovered_devices_.erase(device_id);
283   FOR_EACH_OBSERVER(Observer, observers_, DiscoveredDevicesListChanged());
284 }
285
286 void FakeControllerPairingController::PairingStageChanged(Stage new_stage) {
287   Stage next_stage = STAGE_NONE;
288   switch (new_stage) {
289     case STAGE_DEVICES_DISCOVERY: {
290       discovered_devices_.clear();
291       base::MessageLoop::current()->PostDelayedTask(
292           FROM_HERE,
293           base::Bind(&FakeControllerPairingController::ExecuteDiscoveryEvent,
294                      base::Unretained(this),
295                      0),
296           async_duration_);
297       break;
298     }
299     case STAGE_ESTABLISHING_CONNECTION: {
300       if (should_fail_on_connecting_) {
301         next_stage = STAGE_ESTABLISHING_CONNECTION_ERROR;
302         should_fail_on_connecting_ = false;
303       } else {
304         confirmation_code_.clear();
305         next_stage = STAGE_WAITING_FOR_CODE_CONFIRMATION;
306       }
307       break;
308     }
309     case STAGE_HOST_UPDATE_IN_PROGRESS: {
310       next_stage = STAGE_WAITING_FOR_CREDENTIALS;
311       break;
312     }
313     case STAGE_HOST_ENROLLMENT_IN_PROGRESS: {
314       if (enrollment_should_fail_) {
315         enrollment_should_fail_ = false;
316         next_stage = STAGE_HOST_ENROLLMENT_ERROR;
317       } else {
318         next_stage = STAGE_HOST_ENROLLMENT_SUCCESS;
319       }
320       break;
321     }
322     case STAGE_HOST_CONNECTION_LOST: {
323       next_stage = connection_lost_end_;
324       connection_lost_end_ = STAGE_NONE;
325       break;
326     }
327     default:
328       break;
329   }
330   if (new_stage == connection_lost_begin_) {
331     connection_lost_begin_ = STAGE_NONE;
332     next_stage = STAGE_HOST_CONNECTION_LOST;
333   }
334   if (next_stage != STAGE_NONE)
335     ChangeStageLater(next_stage);
336 }
337
338 void FakeControllerPairingController::DiscoveredDevicesListChanged() {
339 }
340
341 }  // namespace pairing_chromeos