| 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 |