Upstream version 9.38.198.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 (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 pairing_chromeos