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.
5 #include "chrome/browser/chromeos/login/screens/controller_pairing_screen.h"
7 #include "base/command_line.h"
8 #include "base/values.h"
9 #include "chrome/browser/chromeos/login/wizard_controller.h"
10 #include "google_apis/gaia/gaia_auth_util.h"
12 using namespace chromeos::controller_pairing;
13 using namespace pairing_chromeos;
17 ControllerPairingScreen::ControllerPairingScreen(
18 BaseScreenDelegate* base_screen_delegate,
20 ControllerPairingScreenActor* actor,
21 ControllerPairingController* shark_controller)
22 : BaseScreen(base_screen_delegate),
25 shark_controller_(shark_controller),
26 current_stage_(ControllerPairingController::STAGE_NONE),
27 device_preselected_(false) {
28 actor_->SetDelegate(this);
29 shark_controller_->AddObserver(this);
32 ControllerPairingScreen::~ControllerPairingScreen() {
34 actor_->SetDelegate(NULL);
35 shark_controller_->RemoveObserver(this);
38 void ControllerPairingScreen::CommitContextChanges() {
39 if (!context_.HasChanges())
41 base::DictionaryValue diff;
42 context_.GetChangesAndReset(&diff);
44 actor_->OnContextChanged(diff);
47 bool ControllerPairingScreen::ExpectStageIs(Stage stage) const {
48 DCHECK(stage == current_stage_);
49 if (current_stage_ != stage)
50 LOG(ERROR) << "Incorrect stage. Expected: " << stage
51 << ", current stage: " << current_stage_;
52 return stage == current_stage_;
55 void ControllerPairingScreen::PrepareToShow() {
58 void ControllerPairingScreen::Show() {
61 shark_controller_->StartPairing();
64 void ControllerPairingScreen::Hide() {
69 std::string ControllerPairingScreen::GetName() const {
70 return WizardController::kControllerPairingScreenName;
73 void ControllerPairingScreen::PairingStageChanged(Stage new_stage) {
74 DCHECK(new_stage != current_stage_);
76 std::string desired_page;
78 case ControllerPairingController::STAGE_DEVICES_DISCOVERY: {
79 desired_page = kPageDevicesDiscovery;
80 context_.SetStringList(kContextKeyDevices, ::login::StringList());
81 context_.SetString(kContextKeySelectedDevice, std::string());
82 device_preselected_ = false;
85 case ControllerPairingController::STAGE_DEVICE_NOT_FOUND: {
86 desired_page = kPageDeviceNotFound;
89 case ControllerPairingController::STAGE_ESTABLISHING_CONNECTION: {
90 desired_page = kPageEstablishingConnection;
93 case ControllerPairingController::STAGE_ESTABLISHING_CONNECTION_ERROR: {
94 desired_page = kPageEstablishingConnectionError;
97 case ControllerPairingController::STAGE_WAITING_FOR_CODE_CONFIRMATION: {
98 desired_page = kPageCodeConfirmation;
99 context_.SetString(kContextKeyConfirmationCode,
100 shark_controller_->GetConfirmationCode());
103 case ControllerPairingController::STAGE_PAIRING_DONE: {
105 delegate_->SetHostConfiguration();
108 case ControllerPairingController::STAGE_HOST_UPDATE_IN_PROGRESS: {
109 desired_page = kPageHostUpdate;
112 case ControllerPairingController::STAGE_HOST_CONNECTION_LOST: {
113 desired_page = kPageHostConnectionLost;
116 case ControllerPairingController::STAGE_WAITING_FOR_CREDENTIALS: {
117 shark_controller_->RemoveObserver(this);
118 get_base_screen_delegate()->OnExit(
119 WizardController::CONTROLLER_PAIRING_FINISHED);
120 desired_page = kPageEnrollmentIntroduction;
123 case ControllerPairingController::STAGE_INITIALIZATION_ERROR: {
124 // TODO(achuith, dzhioev, zork): Handle this better.
125 LOG(WARNING) << "Bluetooth initialization error";
131 current_stage_ = new_stage;
132 context_.SetString(kContextKeyPage, desired_page);
133 context_.SetBoolean(kContextKeyControlsDisabled, false);
134 CommitContextChanges();
135 VLOG(1) << "PairingStageChanged " << desired_page
136 << ", current stage " << current_stage_;
139 void ControllerPairingScreen::DiscoveredDevicesListChanged() {
140 if (!ExpectStageIs(ControllerPairingController::STAGE_DEVICES_DISCOVERY))
142 ControllerPairingController::DeviceIdList devices =
143 shark_controller_->GetDiscoveredDevices();
144 std::sort(devices.begin(), devices.end());
145 context_.SetStringList(kContextKeyDevices, devices);
148 devices.empty() ? kPageDevicesDiscovery : kPageDeviceSelect);
149 std::string selected_device = context_.GetString(kContextKeySelectedDevice);
150 if (std::find(devices.begin(), devices.end(), selected_device) ==
152 selected_device.clear();
154 if (devices.empty()) {
155 device_preselected_ = false;
156 } else if (!device_preselected_) {
157 selected_device = devices.front();
158 device_preselected_ = true;
160 context_.SetString(kContextKeySelectedDevice, selected_device);
161 context_.SetBoolean(kContextKeyControlsDisabled, selected_device.empty());
162 CommitContextChanges();
165 void ControllerPairingScreen::OnActorDestroyed(
166 ControllerPairingScreenActor* actor) {
171 // Overridden from ControllerPairingView::Delegate:
172 void ControllerPairingScreen::OnUserActed(const std::string& action) {
173 if (context_.GetBoolean(kContextKeyControlsDisabled)) {
174 LOG(WARNING) << "User acted, but controls are disabled. Ignoring.";
177 bool disable_controls = true;
178 if (action == kActionChooseDevice) {
179 std::string selectedDevice = context_.GetString(kContextKeySelectedDevice);
180 if (selectedDevice.empty())
181 LOG(ERROR) << "Device was not selected.";
183 shark_controller_->ChooseDeviceForPairing(selectedDevice);
184 } else if (action == kActionRepeatDiscovery) {
185 shark_controller_->RepeatDiscovery();
186 } else if (action == kActionAcceptCode) {
187 shark_controller_->SetConfirmationCodeIsCorrect(true);
188 } else if (action == kActionRejectCode) {
189 shark_controller_->SetConfirmationCodeIsCorrect(false);
190 } else if (action == kActionProceedToAuthentication) {
191 context_.SetString(kContextKeyPage, kPageAuthentication);
192 disable_controls = false;
193 } else if (action == kActionEnroll) {
194 const std::string account_id =
195 gaia::SanitizeEmail(context_.GetString(kContextKeyAccountId));
196 const std::string domain(gaia::ExtractDomainName(account_id));
197 context_.SetString(kContextKeyEnrollmentDomain, domain);
198 } else if (action == kActionStartSession) {
199 shark_controller_->StartSession();
201 context_.SetBoolean(kContextKeyControlsDisabled, disable_controls);
202 CommitContextChanges();
205 void ControllerPairingScreen::OnScreenContextChanged(
206 const base::DictionaryValue& diff) {
207 std::vector<std::string> changedKeys;
208 context_.ApplyChanges(diff, &changedKeys);
209 for (std::vector<std::string>::const_iterator key = changedKeys.begin();
210 key != changedKeys.end();
212 if (*key == kContextKeySelectedDevice) {
213 context_.SetBoolean(kContextKeyControlsDisabled,
214 context_.GetString(*key).empty());
215 CommitContextChanges();
220 } // namespace chromeos