summaryrefslogtreecommitdiffstats
path: root/components/pairing/fake_controller_pairing_controller.cc
diff options
context:
space:
mode:
Diffstat (limited to 'components/pairing/fake_controller_pairing_controller.cc')
-rw-r--r--components/pairing/fake_controller_pairing_controller.cc335
1 files changed, 335 insertions, 0 deletions
diff --git a/components/pairing/fake_controller_pairing_controller.cc b/components/pairing/fake_controller_pairing_controller.cc
new file mode 100644
index 0000000..deb8615
--- /dev/null
+++ b/components/pairing/fake_controller_pairing_controller.cc
@@ -0,0 +1,335 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/pairing/fake_controller_pairing_controller.h"
+
+#include <map>
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "base/rand_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+
+namespace pairing_chromeos {
+
+FakeControllerPairingController::FakeControllerPairingController(
+ const std::string& config)
+ : current_stage_(STAGE_NONE),
+ should_fail_on_connecting_(false),
+ connection_lost_begin_(STAGE_NONE),
+ connection_lost_end_(STAGE_NONE),
+ enrollment_should_fail_(false) {
+ ApplyConfig(config);
+ AddObserver(this);
+}
+
+FakeControllerPairingController::~FakeControllerPairingController() {
+ RemoveObserver(this);
+}
+
+void FakeControllerPairingController::ApplyConfig(const std::string& config) {
+ typedef std::vector<std::string> Tokens;
+
+ base::StringPairs kv_pairs;
+ CHECK(base::SplitStringIntoKeyValuePairs(config, ':', ',', &kv_pairs))
+ << "Wrong config format.";
+ std::map<std::string, std::string> dict(kv_pairs.begin(), kv_pairs.end());
+
+ if (dict.count("async_duration")) {
+ int ms = 0;
+ CHECK(base::StringToInt(dict["async_duration"], &ms))
+ << "Wrong 'async_duration' format.";
+ async_duration_ = base::TimeDelta::FromMilliseconds(ms);
+ } else {
+ async_duration_ = base::TimeDelta::FromMilliseconds(3000);
+ }
+
+ should_fail_on_connecting_ =
+ dict.count("fail_connecting") && (dict["fail_connecting"] == "1");
+
+ enrollment_should_fail_ =
+ dict.count("fail_enrollment") && (dict["fail_enrollment"] == "1");
+
+ if (dict.count("connection_lost")) {
+ Tokens lost_begin_end;
+ CHECK(Tokenize(dict["connection_lost"], "-", &lost_begin_end) == 2)
+ << "Wrong 'connection_lost' format.";
+ int begin = 0;
+ int end = 0;
+ CHECK(base::StringToInt(lost_begin_end[0], &begin) &&
+ base::StringToInt(lost_begin_end[1], &end))
+ << "Wrong 'connection_lost' format.";
+ CHECK((begin == 0 && end == 0) ||
+ (STAGE_WAITING_FOR_CODE_CONFIRMATION <= begin && begin <= end &&
+ end <= STAGE_HOST_ENROLLMENT_ERROR))
+ << "Wrong 'connection_lost' interval.";
+ connection_lost_begin_ = static_cast<Stage>(begin);
+ connection_lost_end_ = static_cast<Stage>(end);
+ } else {
+ connection_lost_begin_ = connection_lost_end_ = STAGE_NONE;
+ }
+
+ if (!dict.count("discovery")) {
+ dict["discovery"] =
+ "F-Device_1~F-Device_5~F-Device_3~L-Device_3~L-Device_1~F-Device_1";
+ }
+ base::StringPairs events;
+ CHECK(
+ base::SplitStringIntoKeyValuePairs(dict["discovery"], '-', '~', &events))
+ << "Wrong 'discovery' format.";
+ DiscoveryScenario scenario;
+ for (base::StringPairs::const_iterator event = events.begin();
+ event != events.end();
+ ++event) {
+ std::string type = event->first;
+ std::string device_id = event->second;
+ CHECK(type == "F" || type == "L" || type == "N")
+ << "Wrong discovery event type.";
+ CHECK(!device_id.empty() || type == "N") << "Empty device ID.";
+ scenario.push_back(DiscoveryEvent(
+ type == "F" ? DEVICE_FOUND : type == "L" ? DEVICE_LOST : NOTHING_FOUND,
+ device_id));
+ }
+ SetDiscoveryScenario(scenario);
+
+ preset_confirmation_code_ = dict["code"];
+ CHECK(preset_confirmation_code_.empty() ||
+ (preset_confirmation_code_.length() == 6 &&
+ preset_confirmation_code_.find_first_not_of("0123456789") ==
+ std::string::npos))
+ << "Wrong 'code' format.";
+}
+
+void FakeControllerPairingController::SetShouldFailOnConnecting() {
+ should_fail_on_connecting_ = true;
+}
+
+void FakeControllerPairingController::SetShouldLoseConnection(Stage stage_begin,
+ Stage stage_end) {
+ connection_lost_begin_ = stage_begin;
+ connection_lost_end_ = stage_end;
+}
+
+void FakeControllerPairingController::SetEnrollmentShouldFail() {
+ enrollment_should_fail_ = true;
+}
+
+void FakeControllerPairingController::SetDiscoveryScenario(
+ const DiscoveryScenario& discovery_scenario) {
+ discovery_scenario_ = discovery_scenario;
+ // Check that scenario is valid.
+ std::set<std::string> devices;
+ for (DiscoveryScenario::const_iterator event = discovery_scenario_.begin();
+ event != discovery_scenario_.end();
+ ++event) {
+ switch (event->first) {
+ case DEVICE_FOUND: {
+ devices.insert(event->second);
+ break;
+ }
+ case DEVICE_LOST: {
+ CHECK(devices.count(event->second));
+ devices.erase(event->second);
+ break;
+ }
+ case NOTHING_FOUND: {
+ CHECK(++event == discovery_scenario_.end());
+ return;
+ }
+ }
+ }
+}
+
+void FakeControllerPairingController::AddObserver(Observer* observer) {
+ observers_.AddObserver(observer);
+}
+
+void FakeControllerPairingController::RemoveObserver(Observer* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+ControllerPairingController::Stage
+FakeControllerPairingController::GetCurrentStage() {
+ return current_stage_;
+}
+
+void FakeControllerPairingController::StartPairing() {
+ CHECK(current_stage_ == STAGE_NONE);
+ ChangeStage(STAGE_DEVICES_DISCOVERY);
+}
+
+ControllerPairingController::DeviceIdList
+FakeControllerPairingController::GetDiscoveredDevices() {
+ CHECK(current_stage_ == STAGE_DEVICES_DISCOVERY);
+ return DeviceIdList(discovered_devices_.begin(), discovered_devices_.end());
+}
+
+void FakeControllerPairingController::ChooseDeviceForPairing(
+ const std::string& device_id) {
+ CHECK(current_stage_ == STAGE_DEVICES_DISCOVERY);
+ CHECK(discovered_devices_.count(device_id));
+ choosen_device_ = device_id;
+ ChangeStage(STAGE_ESTABLISHING_CONNECTION);
+}
+
+void FakeControllerPairingController::RepeatDiscovery() {
+ CHECK(current_stage_ == STAGE_DEVICE_NOT_FOUND ||
+ current_stage_ == STAGE_ESTABLISHING_CONNECTION_ERROR ||
+ current_stage_ == STAGE_HOST_ENROLLMENT_ERROR);
+ ChangeStage(STAGE_DEVICES_DISCOVERY);
+}
+
+std::string FakeControllerPairingController::GetConfirmationCode() {
+ CHECK(current_stage_ == STAGE_WAITING_FOR_CODE_CONFIRMATION);
+ if (confirmation_code_.empty()) {
+ if (preset_confirmation_code_.empty()) {
+ for (int i = 0; i < 6; ++i)
+ confirmation_code_.push_back(base::RandInt('0', '9'));
+ } else {
+ confirmation_code_ = preset_confirmation_code_;
+ }
+ }
+ return confirmation_code_;
+}
+
+void FakeControllerPairingController::SetConfirmationCodeIsCorrect(
+ bool correct) {
+ CHECK(current_stage_ == STAGE_WAITING_FOR_CODE_CONFIRMATION);
+ if (correct)
+ ChangeStage(STAGE_HOST_UPDATE_IN_PROGRESS);
+ else
+ ChangeStage(STAGE_DEVICES_DISCOVERY);
+}
+
+void FakeControllerPairingController::OnAuthenticationDone(
+ const chromeos::UserContext& user_context,
+ content::BrowserContext* browser_context) {
+ CHECK(current_stage_ == STAGE_WAITING_FOR_CREDENTIALS);
+ ChangeStage(STAGE_HOST_ENROLLMENT_IN_PROGRESS);
+}
+
+void FakeControllerPairingController::StartSession() {
+ CHECK(current_stage_ == STAGE_PAIRING_DONE);
+ ChangeStage(STAGE_FINISHED);
+}
+
+void FakeControllerPairingController::ChangeStage(Stage new_stage) {
+ if (current_stage_ == new_stage)
+ return;
+ current_stage_ = new_stage;
+ FOR_EACH_OBSERVER(Observer, observers_, PairingStageChanged(new_stage));
+}
+
+void FakeControllerPairingController::ChangeStageLater(Stage new_stage) {
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&FakeControllerPairingController::ChangeStage,
+ base::Unretained(this),
+ new_stage),
+ async_duration_);
+}
+
+void FakeControllerPairingController::ExecuteDiscoveryEvent(
+ size_t event_position) {
+ if (current_stage_ != STAGE_DEVICES_DISCOVERY)
+ return;
+ CHECK(event_position < discovery_scenario_.size());
+ const DiscoveryEvent& event = discovery_scenario_[event_position];
+ switch (event.first) {
+ case DEVICE_FOUND: {
+ DeviceFound(event.second);
+ break;
+ }
+ case DEVICE_LOST: {
+ DeviceLost(event.second);
+ break;
+ }
+ case NOTHING_FOUND: {
+ ChangeStage(STAGE_DEVICE_NOT_FOUND);
+ break;
+ }
+ }
+ if (++event_position == discovery_scenario_.size()) {
+ return;
+ }
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&FakeControllerPairingController::ExecuteDiscoveryEvent,
+ base::Unretained(this),
+ event_position),
+ async_duration_);
+}
+
+void FakeControllerPairingController::DeviceFound(
+ const std::string& device_id) {
+ CHECK(current_stage_ == STAGE_DEVICES_DISCOVERY);
+ discovered_devices_.insert(device_id);
+ FOR_EACH_OBSERVER(Observer, observers_, DiscoveredDevicesListChanged());
+}
+
+void FakeControllerPairingController::DeviceLost(const std::string& device_id) {
+ CHECK(current_stage_ == STAGE_DEVICES_DISCOVERY);
+ discovered_devices_.erase(device_id);
+ FOR_EACH_OBSERVER(Observer, observers_, DiscoveredDevicesListChanged());
+}
+
+void FakeControllerPairingController::PairingStageChanged(Stage new_stage) {
+ Stage next_stage = STAGE_NONE;
+ switch (new_stage) {
+ case STAGE_DEVICES_DISCOVERY: {
+ discovered_devices_.clear();
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&FakeControllerPairingController::ExecuteDiscoveryEvent,
+ base::Unretained(this),
+ 0),
+ async_duration_);
+ break;
+ }
+ case STAGE_ESTABLISHING_CONNECTION: {
+ if (should_fail_on_connecting_) {
+ next_stage = STAGE_ESTABLISHING_CONNECTION_ERROR;
+ should_fail_on_connecting_ = false;
+ } else {
+ confirmation_code_.clear();
+ next_stage = STAGE_WAITING_FOR_CODE_CONFIRMATION;
+ }
+ break;
+ }
+ case STAGE_HOST_UPDATE_IN_PROGRESS: {
+ next_stage = STAGE_WAITING_FOR_CREDENTIALS;
+ break;
+ }
+ case STAGE_HOST_ENROLLMENT_IN_PROGRESS: {
+ if (enrollment_should_fail_) {
+ enrollment_should_fail_ = false;
+ next_stage = STAGE_HOST_ENROLLMENT_ERROR;
+ } else {
+ next_stage = STAGE_PAIRING_DONE;
+ }
+ break;
+ }
+ case STAGE_HOST_CONNECTION_LOST: {
+ next_stage = connection_lost_end_;
+ connection_lost_end_ = STAGE_NONE;
+ break;
+ }
+ default:
+ break;
+ }
+ if (new_stage == connection_lost_begin_) {
+ connection_lost_begin_ = STAGE_NONE;
+ next_stage = STAGE_HOST_CONNECTION_LOST;
+ }
+ if (next_stage != STAGE_NONE)
+ ChangeStageLater(next_stage);
+}
+
+void FakeControllerPairingController::DiscoveredDevicesListChanged() {
+}
+
+} // namespace pairing_chromeos