diff options
author | zork@chromium.org <zork@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-22 00:17:38 +0000 |
---|---|---|
committer | zork@chromium.org <zork@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-22 00:17:38 +0000 |
commit | 7d54a19568afcc4912539e1cfb5356e27a5ec718 (patch) | |
tree | 5427322d7970456deb197f261c3a2f92d1dffb24 /components/pairing | |
parent | 90e1a1b9c8af2649dd56e29ee35776d7446f31c2 (diff) | |
download | chromium_src-7d54a19568afcc4912539e1cfb5356e27a5ec718.zip chromium_src-7d54a19568afcc4912539e1cfb5356e27a5ec718.tar.gz chromium_src-7d54a19568afcc4912539e1cfb5356e27a5ec718.tar.bz2 |
Move Chrome OS pairing interface to chrome/browser/chromeos
BUG=393413
Review URL: https://codereview.chromium.org/387163002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@284549 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'components/pairing')
-rw-r--r-- | components/pairing/BUILD.gn | 21 | ||||
-rw-r--r-- | components/pairing/DEPS | 3 | ||||
-rw-r--r-- | components/pairing/OWNERS | 3 | ||||
-rw-r--r-- | components/pairing/controller_pairing_controller.cc | 21 | ||||
-rw-r--r-- | components/pairing/controller_pairing_controller.h | 108 | ||||
-rw-r--r-- | components/pairing/fake_controller_pairing_controller.cc | 335 | ||||
-rw-r--r-- | components/pairing/fake_controller_pairing_controller.h | 110 | ||||
-rw-r--r-- | components/pairing/fake_host_pairing_controller.cc | 192 | ||||
-rw-r--r-- | components/pairing/fake_host_pairing_controller.h | 73 | ||||
-rw-r--r-- | components/pairing/host_pairing_controller.cc | 16 | ||||
-rw-r--r-- | components/pairing/host_pairing_controller.h | 79 |
11 files changed, 961 insertions, 0 deletions
diff --git a/components/pairing/BUILD.gn b/components/pairing/BUILD.gn new file mode 100644 index 0000000..5022bc5 --- /dev/null +++ b/components/pairing/BUILD.gn @@ -0,0 +1,21 @@ +# 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. + +source_set("pairing") { + sources = [ + "pairing/fake_controller_pairing_controller.cc", + "pairing/fake_controller_pairing_controller.h", + "pairing/fake_host_pairing_controller.cc", + "pairing/fake_host_pairing_controller.h", + "pairing/controller_pairing_controller.cc", + "pairing/controller_pairing_controller.h", + "pairing/host_pairing_controller.cc", + "pairing/host_pairing_controller.h", + ] + + deps = [ + "//base", + "//device/bluetooth", + ] +} diff --git a/components/pairing/DEPS b/components/pairing/DEPS new file mode 100644 index 0000000..78c9970 --- /dev/null +++ b/components/pairing/DEPS @@ -0,0 +1,3 @@ +include_rules = [ + "+device/bluetooth", +] diff --git a/components/pairing/OWNERS b/components/pairing/OWNERS new file mode 100644 index 0000000..14942e3 --- /dev/null +++ b/components/pairing/OWNERS @@ -0,0 +1,3 @@ +achuith@chromium.org +dzhioev@chromium.org +zork@chromium.org diff --git a/components/pairing/controller_pairing_controller.cc b/components/pairing/controller_pairing_controller.cc new file mode 100644 index 0000000..448332f --- /dev/null +++ b/components/pairing/controller_pairing_controller.cc @@ -0,0 +1,21 @@ +// 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/controller_pairing_controller.h" + +namespace pairing_chromeos { + +ControllerPairingController::Observer::Observer() { +} + +ControllerPairingController::Observer::~Observer() { +} + +ControllerPairingController::ControllerPairingController() { +} + +ControllerPairingController::~ControllerPairingController() { +} + +} // namespace pairing_chromeos diff --git a/components/pairing/controller_pairing_controller.h b/components/pairing/controller_pairing_controller.h new file mode 100644 index 0000000..67ec581 --- /dev/null +++ b/components/pairing/controller_pairing_controller.h @@ -0,0 +1,108 @@ +// 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. + +#ifndef COMPONENTS_PAIRING_CONTROLLER_PAIRING_CONTROLLER_H_ +#define COMPONENTS_PAIRING_CONTROLLER_PAIRING_CONTROLLER_H_ + +#include <string> +#include <vector> + +#include "base/macros.h" + +namespace chromeos { +class UserContext; +} + +namespace content { +class BrowserContext; +} + +namespace pairing_chromeos { + +class ControllerPairingController { + public: + enum Stage { + STAGE_NONE, + STAGE_DEVICES_DISCOVERY, + STAGE_DEVICE_NOT_FOUND, + STAGE_ESTABLISHING_CONNECTION, + STAGE_ESTABLISHING_CONNECTION_ERROR, + STAGE_WAITING_FOR_CODE_CONFIRMATION, + STAGE_HOST_UPDATE_IN_PROGRESS, + STAGE_HOST_CONNECTION_LOST, + STAGE_WAITING_FOR_CREDENTIALS, + STAGE_HOST_ENROLLMENT_IN_PROGRESS, + STAGE_HOST_ENROLLMENT_ERROR, + STAGE_PAIRING_DONE, + STAGE_FINISHED + }; + + class Observer { + public: + Observer(); + virtual ~Observer(); + + // Called when pairing has moved on from one stage to another. + virtual void PairingStageChanged(Stage new_stage) = 0; + + // Called when new device was discovered or existing device was lost. + // This notification is made only on |STAGE_DEVICES_DISCOVERY| stage. + virtual void DiscoveredDevicesListChanged() = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(Observer); + }; + + typedef std::vector<std::string> DeviceIdList; + + ControllerPairingController(); + virtual ~ControllerPairingController(); + + virtual void AddObserver(Observer* observer) = 0; + virtual void RemoveObserver(Observer* observer) = 0; + + // Returns current stage of pairing process. + virtual Stage GetCurrentStage() = 0; + + // Starts pairing process. Can be called only on |STAGE_NONE| stage. + virtual void StartPairing() = 0; + + // Returns list of discovered devices. Can be called only on + // |STAGE_DEVICES_DISCOVERY| stage. + virtual DeviceIdList GetDiscoveredDevices() = 0; + + // This method is called to start pairing with the device having |device_id| + // ID. Can be called only on |STAGE_DEVICES_DISCOVERY| stage. + virtual void ChooseDeviceForPairing(const std::string& device_id) = 0; + + // Rescan for devices to pair with. Can be called only on + // stages |STAGE_DEVICE_NOT_FOUND|, |STAGE_ESTABLISHING_CONNECTION_ERROR|, + // |STAGE_HOST_ENROLLMENT_ERROR|. + virtual void RepeatDiscovery() = 0; + + // Returns pairing confirmation code. + // Could be called only on |STATE_WAITING_FOR_CODE_CONFIRMATION| stage. + virtual std::string GetConfirmationCode() = 0; + + // Called to confirm or deny confirmation code. Can be called only on + // |STAGE_WAITING_FOR_CODE_CONFIRMATION| stage. + virtual void SetConfirmationCodeIsCorrect(bool correct) = 0; + + // Called when user successfully authenticated on GAIA page. Can be called + // only on |STAGE_WAITING_FOR_CREDENTIALS| stage. + virtual void OnAuthenticationDone( + const chromeos::UserContext& user_context, + content::BrowserContext* browser_context) = 0; + + // Installs app and starts session. + // Can be called only on |STAGE_PAIRING_DONE| stage. + virtual void StartSession() = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(ControllerPairingController); +}; + +} // namespace pairing_chromeos + +#endif // COMPONENTS_PAIRING_CONTROLLER_PAIRING_CONTROLLER_H_ 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 diff --git a/components/pairing/fake_controller_pairing_controller.h b/components/pairing/fake_controller_pairing_controller.h new file mode 100644 index 0000000..ce6630a --- /dev/null +++ b/components/pairing/fake_controller_pairing_controller.h @@ -0,0 +1,110 @@ +// 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. + +#ifndef COMPONENTS_PAIRING_FAKE_CONTROLLER_PAIRING_CONTROLLER_H_ +#define COMPONENTS_PAIRING_FAKE_CONTROLLER_PAIRING_CONTROLLER_H_ + +#include <set> +#include <utility> + +#include "base/macros.h" +#include "base/observer_list.h" +#include "base/time/time.h" +#include "components/pairing/controller_pairing_controller.h" + +namespace pairing_chromeos { + +class FakeControllerPairingController + : public ControllerPairingController, + public ControllerPairingController::Observer { + public: + typedef ControllerPairingController::Observer Observer; + + enum DiscoveryEventType { DEVICE_FOUND, DEVICE_LOST, NOTHING_FOUND }; + + typedef std::pair<DiscoveryEventType, std::string> DiscoveryEvent; + typedef std::vector<DiscoveryEvent> DiscoveryScenario; + + // Config is a coma separated list of key-value pairs separated by colon. + // Supported options: + // * async_duration - integer. Default: 3000. + // * fail_connecting - {0,1}. Default: 0. + // * connection_lost - integer-integer. Default: 0-0. + // * fail_enrollment - {0,1}. Default: 0. + // * discovery - {F,L,N}-string(~{F,L,N}-string)*. Default: + // F-Device_1~F-Device_5~F-Device_3~L-Device_3~L-Device_1~F-Device_1 + // * code - 6 digits or empty string. Default: empty string. If strings is + // empty, random code is generated. + explicit FakeControllerPairingController(const std::string& config); + virtual ~FakeControllerPairingController(); + + // Applies given |config| to controller. + void ApplyConfig(const std::string& config); + + // Sets delay for asynchronous operations. like device searching or host + // enrollment. Default value is 3 seconds. + void set_async_duration(base::TimeDelta async_duration) { + async_duration_ = async_duration; + } + + // Causing an error on |STAGE_ESTABLISHING_CONNECTION| stage once. + void SetShouldFailOnConnecting(); + + // Causing a connection loss on |stage_begin| and a connection recovery + // on |stage_end| once. + void SetShouldLoseConnection(Stage stage_begin, Stage stage_end); + + // Makes host enrollment to fail once. + void SetEnrollmentShouldFail(); + + // Sets devices discovery scenario for |STAGE_DEVICES_DESCOVERY| stage. + // Events are executed with interval of |async_duration_|. + // For default scenario refer to implementation. + void SetDiscoveryScenario(const DiscoveryScenario& discovery_scenario); + + // Overridden from ControllerPairingController: + virtual void AddObserver(Observer* observer) OVERRIDE; + virtual void RemoveObserver(Observer* observer) OVERRIDE; + virtual Stage GetCurrentStage() OVERRIDE; + virtual void StartPairing() OVERRIDE; + virtual DeviceIdList GetDiscoveredDevices() OVERRIDE; + virtual void ChooseDeviceForPairing(const std::string& device_id) OVERRIDE; + virtual void RepeatDiscovery() OVERRIDE; + virtual std::string GetConfirmationCode() OVERRIDE; + virtual void SetConfirmationCodeIsCorrect(bool correct) OVERRIDE; + virtual void OnAuthenticationDone( + const chromeos::UserContext& user_context, + content::BrowserContext* browser_context) OVERRIDE; + virtual void StartSession() OVERRIDE; + + private: + void ChangeStage(Stage new_stage); + void ChangeStageLater(Stage new_stage); + void ExecuteDiscoveryEvent(size_t event_position); + void DeviceFound(const std::string& device_id); + void DeviceLost(const std::string& device_id); + + // Overridden from ui::ControllerPairingController::Observer: + virtual void PairingStageChanged(Stage new_stage) OVERRIDE; + virtual void DiscoveredDevicesListChanged() OVERRIDE; + + ObserverList<ControllerPairingController::Observer> observers_; + Stage current_stage_; + std::string confirmation_code_; + std::string preset_confirmation_code_; + base::TimeDelta async_duration_; + DiscoveryScenario discovery_scenario_; + std::set<std::string> discovered_devices_; + std::string choosen_device_; + bool should_fail_on_connecting_; + Stage connection_lost_begin_; + Stage connection_lost_end_; + bool enrollment_should_fail_; + + DISALLOW_COPY_AND_ASSIGN(FakeControllerPairingController); +}; + +} // namespace pairing_chromeos + +#endif // COMPONENTS_PAIRING_FAKE_CONTROLLER_PAIRING_CONTROLLER_H_ diff --git a/components/pairing/fake_host_pairing_controller.cc b/components/pairing/fake_host_pairing_controller.cc new file mode 100644 index 0000000..b2af9b0 --- /dev/null +++ b/components/pairing/fake_host_pairing_controller.cc @@ -0,0 +1,192 @@ +// 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_host_pairing_controller.h" + +#include <map> +#include <vector> + +#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" + +namespace { + +const int kUpdateStepsNumber = 10; +const int kDefaultAsyncDurationMs = 3000; +const size_t kCodeLength = 6; + +} // namespace + +namespace pairing_chromeos { + +FakeHostPairingController::FakeHostPairingController(const std::string& config) + : current_stage_(STAGE_NONE), + enrollment_should_fail_(false), + start_after_update_(false) { + ApplyConfig(config); + AddObserver(this); +} + +FakeHostPairingController::~FakeHostPairingController() { + RemoveObserver(this); +} + +void FakeHostPairingController::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(kDefaultAsyncDurationMs); + } + + start_after_update_ = dict["start_after_update"] == "1"; + + enrollment_should_fail_ = dict["fail_enrollment"] == "1"; + + if (dict.count("code")) { + confirmation_code_ = dict["code"]; + } else { + confirmation_code_.clear(); + for (size_t i = 0; i < kCodeLength; ++i) + confirmation_code_.push_back(base::RandInt('0', '9')); + } + CHECK(confirmation_code_.length() == kCodeLength && + confirmation_code_.find_first_not_of("0123456789") == std::string::npos) + << "Wrong 'code' format."; + + device_name_ = + dict.count("device_name") ? dict["device_name"] : "Chromebox-01"; + + enrollment_domain_ = dict.count("domain") ? dict["domain"] : "example.com"; +} + +void FakeHostPairingController::ChangeStage(Stage new_stage) { + if (current_stage_ == new_stage) + return; + current_stage_ = new_stage; + FOR_EACH_OBSERVER(Observer, observers_, PairingStageChanged(new_stage)); +} + +void FakeHostPairingController::ChangeStageLater(Stage new_stage) { + base::MessageLoop::current()->PostDelayedTask( + FROM_HERE, + base::Bind(&FakeHostPairingController::ChangeStage, + base::Unretained(this), + new_stage), + async_duration_); +} + +void FakeHostPairingController::SetUpdateProgress(int step) { + UpdateProgress progress; + progress.progress = double(step) / kUpdateStepsNumber; + FOR_EACH_OBSERVER(Observer, observers_, UpdateAdvanced(progress)); + base::Closure task; + if (step >= kUpdateStepsNumber) { + task = base::Bind(&FakeHostPairingController::ChangeStage, + base::Unretained(this), + STAGE_WAITING_FOR_CONTROLLER_AFTER_UPDATE); + } else { + task = base::Bind(&FakeHostPairingController::SetUpdateProgress, + base::Unretained(this), + step + 1); + } + base::MessageLoop::current()->PostDelayedTask( + FROM_HERE, task, async_duration_ / kUpdateStepsNumber); +} + +void FakeHostPairingController::AddObserver(Observer* observer) { + observers_.AddObserver(observer); +} + +void FakeHostPairingController::RemoveObserver(Observer* observer) { + observers_.RemoveObserver(observer); +} + +HostPairingController::Stage FakeHostPairingController::GetCurrentStage() { + return current_stage_; +} + +void FakeHostPairingController::StartPairing() { + CHECK(current_stage_ == STAGE_NONE); + if (start_after_update_) { + ChangeStage(STAGE_WAITING_FOR_CONTROLLER_AFTER_UPDATE); + } else { + ChangeStage(STAGE_WAITING_FOR_CONTROLLER); + } +} + +std::string FakeHostPairingController::GetDeviceName() { + return device_name_; +} + +std::string FakeHostPairingController::GetConfirmationCode() { + CHECK(current_stage_ == STAGE_WAITING_FOR_CODE_CONFIRMATION); + return confirmation_code_; +} + +std::string FakeHostPairingController::GetEnrollmentDomain() { + return enrollment_domain_; +} + +void FakeHostPairingController::PairingStageChanged(Stage new_stage) { + switch (new_stage) { + case STAGE_WAITING_FOR_CONTROLLER: { + ChangeStageLater(STAGE_WAITING_FOR_CODE_CONFIRMATION); + break; + } + case STAGE_WAITING_FOR_CODE_CONFIRMATION: { + ChangeStageLater(STAGE_UPDATING); + break; + } + case STAGE_UPDATING: { + SetUpdateProgress(0); + break; + } + case STAGE_WAITING_FOR_CONTROLLER_AFTER_UPDATE: { + ChangeStageLater(STAGE_WAITING_FOR_CREDENTIALS); + break; + } + case STAGE_WAITING_FOR_CREDENTIALS: { + ChangeStageLater(STAGE_ENROLLING); + break; + } + case STAGE_ENROLLING: { + if (enrollment_should_fail_) { + enrollment_should_fail_ = false; + ChangeStageLater(STAGE_ENROLLMENT_ERROR); + } else { + ChangeStageLater(STAGE_PAIRING_DONE); + } + break; + } + case STAGE_ENROLLMENT_ERROR: { + ChangeStageLater(STAGE_WAITING_FOR_CONTROLLER_AFTER_UPDATE); + break; + } + case STAGE_PAIRING_DONE: { + ChangeStageLater(STAGE_FINISHED); + break; + } + default: { break; } + } +} + +void FakeHostPairingController::UpdateAdvanced(const UpdateProgress& progress) { +} + +} // namespace pairing_chromeos diff --git a/components/pairing/fake_host_pairing_controller.h b/components/pairing/fake_host_pairing_controller.h new file mode 100644 index 0000000..a071c5e --- /dev/null +++ b/components/pairing/fake_host_pairing_controller.h @@ -0,0 +1,73 @@ +// 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. + +#ifndef COMPONENTS_PAIRING_FAKE_HOST_PAIRING_CONTROLLER_H_ +#define COMPONENTS_PAIRING_FAKE_HOST_PAIRING_CONTROLLER_H_ + +#include "base/macros.h" +#include "base/observer_list.h" +#include "base/time/time.h" +#include "components/pairing/host_pairing_controller.h" + +namespace pairing_chromeos { + +class FakeHostPairingController + : public HostPairingController, + public HostPairingController::Observer { + public: + typedef HostPairingController::Observer Observer; + + // Config is a comma separated list of key-value pairs separated by colon. + // Supported options: + // * async_duration - integer. Default: 3000. + // * start_after_update - {0,1}. Default: 0. + // * fail_enrollment - {0,1}. Default: 0. + // * code - 6 digits or empty string. Default: empty string. If strings is + // empty, random code is generated. + // * device_name - string. Default: "Chromebox-01". + // * domain - string. Default: "example.com". + explicit FakeHostPairingController(const std::string& config); + virtual ~FakeHostPairingController(); + + // Applies given |config| to flow. + void ApplyConfig(const std::string& config); + + // Overridden from HostPairingFlow: + virtual void AddObserver(Observer* observer) OVERRIDE; + virtual void RemoveObserver(Observer* observer) OVERRIDE; + virtual Stage GetCurrentStage() OVERRIDE; + virtual void StartPairing() OVERRIDE; + virtual std::string GetDeviceName() OVERRIDE; + virtual std::string GetConfirmationCode() OVERRIDE; + virtual std::string GetEnrollmentDomain() OVERRIDE; + + private: + void ChangeStage(Stage new_stage); + void ChangeStageLater(Stage new_stage); + void SetUpdateProgress(int step); + + // Overridden from HostPairingFlow::Observer: + virtual void PairingStageChanged(Stage new_stage) OVERRIDE; + virtual void UpdateAdvanced(const UpdateProgress& progress) OVERRIDE; + + ObserverList<Observer> observers_; + Stage current_stage_; + std::string device_name_; + std::string confirmation_code_; + base::TimeDelta async_duration_; + + // If this flag is true error happens on |STAGE_ENROLLING| once. + bool enrollment_should_fail_; + + // Controller starts its work like if update and reboot already happened. + bool start_after_update_; + + std::string enrollment_domain_; + + DISALLOW_COPY_AND_ASSIGN(FakeHostPairingController); +}; + +} // namespace pairing_chromeos + +#endif // COMPONENTS_PAIRING_FAKE_HOST_PAIRING_CONTROLLER_H_ diff --git a/components/pairing/host_pairing_controller.cc b/components/pairing/host_pairing_controller.cc new file mode 100644 index 0000000..be240c9 --- /dev/null +++ b/components/pairing/host_pairing_controller.cc @@ -0,0 +1,16 @@ +// 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/host_pairing_controller.h" + +namespace pairing_chromeos { + +HostPairingController::HostPairingController() {} + +HostPairingController::~HostPairingController() {} + +HostPairingController::Observer::Observer() {} +HostPairingController::Observer::~Observer() {} + +} // namespace pairing_chromeos diff --git a/components/pairing/host_pairing_controller.h b/components/pairing/host_pairing_controller.h new file mode 100644 index 0000000..7d14b6e --- /dev/null +++ b/components/pairing/host_pairing_controller.h @@ -0,0 +1,79 @@ +// 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. + +#ifndef COMPONENTS_PAIRING_HOST_PAIRING_CONTROLLER_H_ +#define COMPONENTS_PAIRING_HOST_PAIRING_CONTROLLER_H_ + +#include <string> + +#include "base/macros.h" + +namespace pairing_chromeos { + +class HostPairingController { + public: + enum Stage { + STAGE_NONE, + STAGE_WAITING_FOR_CONTROLLER, + STAGE_WAITING_FOR_CODE_CONFIRMATION, + STAGE_UPDATING, + STAGE_WAITING_FOR_CONTROLLER_AFTER_UPDATE, + STAGE_WAITING_FOR_CREDENTIALS, + STAGE_ENROLLING, + STAGE_ENROLLMENT_ERROR, + STAGE_PAIRING_DONE, + STAGE_FINISHED + }; + + struct UpdateProgress { + // Number in [0, 1]. + double progress; + }; + + class Observer { + public: + Observer(); + virtual ~Observer(); + + // Called when pairing has moved on from one stage to another. + virtual void PairingStageChanged(Stage new_stage) = 0; + + // Called periodically on |STAGE_UPDATING| stage. Current update progress + // is stored in |progress|. + virtual void UpdateAdvanced(const UpdateProgress& progress) = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(Observer); + }; + + HostPairingController(); + virtual ~HostPairingController(); + + virtual void AddObserver(Observer* observer) = 0; + virtual void RemoveObserver(Observer* observer) = 0; + + // Returns current stage of pairing process. + virtual Stage GetCurrentStage() = 0; + + // Starts pairing process. Can be called only on |STAGE_NONE| stage. + virtual void StartPairing() = 0; + + // Returns device name. + virtual std::string GetDeviceName() = 0; + + // Returns 6-digit confirmation code. Can be called only on + // |STAGE_WAITING_FOR_CODE_CONFIRMATION| stage. + virtual std::string GetConfirmationCode() = 0; + + // Returns an enrollment domain name. Can be called on stage + // |STAGE_ENROLLMENT| and later. + virtual std::string GetEnrollmentDomain() = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(HostPairingController); +}; + +} // namespace pairing_chromeos + +#endif // COMPONENTS_PAIRING_HOST_PAIRING_CONTROLLER_H_ |