summaryrefslogtreecommitdiffstats
path: root/components/pairing
diff options
context:
space:
mode:
authorzork@chromium.org <zork@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-07-22 00:17:38 +0000
committerzork@chromium.org <zork@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-07-22 00:17:38 +0000
commit7d54a19568afcc4912539e1cfb5356e27a5ec718 (patch)
tree5427322d7970456deb197f261c3a2f92d1dffb24 /components/pairing
parent90e1a1b9c8af2649dd56e29ee35776d7446f31c2 (diff)
downloadchromium_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.gn21
-rw-r--r--components/pairing/DEPS3
-rw-r--r--components/pairing/OWNERS3
-rw-r--r--components/pairing/controller_pairing_controller.cc21
-rw-r--r--components/pairing/controller_pairing_controller.h108
-rw-r--r--components/pairing/fake_controller_pairing_controller.cc335
-rw-r--r--components/pairing/fake_controller_pairing_controller.h110
-rw-r--r--components/pairing/fake_host_pairing_controller.cc192
-rw-r--r--components/pairing/fake_host_pairing_controller.h73
-rw-r--r--components/pairing/host_pairing_controller.cc16
-rw-r--r--components/pairing/host_pairing_controller.h79
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_