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 "chrome/browser/chromeos/login/screens/controller_pairing_screen.h" 6 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" 11 12using namespace chromeos::controller_pairing; 13using namespace pairing_chromeos; 14 15namespace chromeos { 16 17ControllerPairingScreen::ControllerPairingScreen( 18 ScreenObserver* observer, 19 ControllerPairingScreenActor* actor, 20 ControllerPairingController* controller) 21 : WizardScreen(observer), 22 actor_(actor), 23 controller_(controller), 24 current_stage_(ControllerPairingController::STAGE_NONE), 25 device_preselected_(false) { 26 actor_->SetDelegate(this); 27 controller_->AddObserver(this); 28} 29 30ControllerPairingScreen::~ControllerPairingScreen() { 31 if (actor_) 32 actor_->SetDelegate(NULL); 33 controller_->RemoveObserver(this); 34} 35 36void ControllerPairingScreen::CommitContextChanges() { 37 if (!context_.HasChanges()) 38 return; 39 base::DictionaryValue diff; 40 context_.GetChangesAndReset(&diff); 41 if (actor_) 42 actor_->OnContextChanged(diff); 43} 44 45bool ControllerPairingScreen::ExpectStageIs(Stage stage) const { 46 DCHECK(stage == current_stage_); 47 if (current_stage_ != stage) 48 LOG(ERROR) << "Incorrect stage. Expected: " << stage 49 << ", current stage: " << current_stage_; 50 return stage == current_stage_; 51} 52 53void ControllerPairingScreen::PrepareToShow() { 54} 55 56void ControllerPairingScreen::Show() { 57 if (actor_) 58 actor_->Show(); 59 controller_->StartPairing(); 60} 61 62void ControllerPairingScreen::Hide() { 63 if (actor_) 64 actor_->Hide(); 65} 66 67std::string ControllerPairingScreen::GetName() const { 68 return WizardController::kControllerPairingScreenName; 69} 70 71// Overridden from ControllerPairingController::Observer: 72void ControllerPairingScreen::PairingStageChanged(Stage new_stage) { 73 DCHECK(new_stage != current_stage_); 74 75 std::string desired_page; 76 switch (new_stage) { 77 case ControllerPairingController::STAGE_DEVICES_DISCOVERY: { 78 desired_page = kPageDevicesDiscovery; 79 context_.SetStringList(kContextKeyDevices, StringList()); 80 context_.SetString(kContextKeySelectedDevice, std::string()); 81 device_preselected_ = false; 82 break; 83 } 84 case ControllerPairingController::STAGE_DEVICE_NOT_FOUND: { 85 desired_page = kPageDeviceNotFound; 86 break; 87 } 88 case ControllerPairingController::STAGE_ESTABLISHING_CONNECTION: { 89 desired_page = kPageEstablishingConnection; 90 break; 91 } 92 case ControllerPairingController::STAGE_ESTABLISHING_CONNECTION_ERROR: { 93 desired_page = kPageEstablishingConnectionError; 94 break; 95 } 96 case ControllerPairingController::STAGE_WAITING_FOR_CODE_CONFIRMATION: { 97 desired_page = kPageCodeConfirmation; 98 context_.SetString(kContextKeyConfirmationCode, 99 controller_->GetConfirmationCode()); 100 break; 101 } 102 case ControllerPairingController::STAGE_HOST_UPDATE_IN_PROGRESS: { 103 desired_page = kPageHostUpdate; 104 break; 105 } 106 case ControllerPairingController::STAGE_HOST_CONNECTION_LOST: { 107 desired_page = kPageHostConnectionLost; 108 break; 109 } 110 case ControllerPairingController::STAGE_WAITING_FOR_CREDENTIALS: { 111 controller_->RemoveObserver(this); 112 get_screen_observer()->OnExit( 113 WizardController::CONTROLLER_PAIRING_FINISHED); 114 // TODO: Move the rest of the stages to the proper location. 115 desired_page = kPageEnrollmentIntroduction; 116 break; 117 } 118 case ControllerPairingController::STAGE_HOST_ENROLLMENT_IN_PROGRESS: { 119 desired_page = kPageHostEnrollment; 120 break; 121 } 122 case ControllerPairingController::STAGE_HOST_ENROLLMENT_ERROR: { 123 desired_page = kPageHostEnrollmentError; 124 break; 125 } 126 case ControllerPairingController::STAGE_PAIRING_DONE: { 127 desired_page = kPagePairingDone; 128 break; 129 } 130 case ControllerPairingController::STAGE_FINISHED: { 131 get_screen_observer()->OnExit( 132 WizardController::CONTROLLER_PAIRING_FINISHED); 133 break; 134 } 135 default: 136 NOTREACHED(); 137 } 138 current_stage_ = new_stage; 139 context_.SetString(kContextKeyPage, desired_page); 140 context_.SetBoolean(kContextKeyControlsDisabled, false); 141 CommitContextChanges(); 142} 143 144void ControllerPairingScreen::DiscoveredDevicesListChanged() { 145 if (!ExpectStageIs(ControllerPairingController::STAGE_DEVICES_DISCOVERY)) 146 return; 147 ControllerPairingController::DeviceIdList devices = 148 controller_->GetDiscoveredDevices(); 149 std::sort(devices.begin(), devices.end()); 150 context_.SetStringList(kContextKeyDevices, devices); 151 context_.SetString( 152 kContextKeyPage, 153 devices.empty() ? kPageDevicesDiscovery : kPageDeviceSelect); 154 std::string selected_device = context_.GetString(kContextKeySelectedDevice); 155 if (std::find(devices.begin(), devices.end(), selected_device) == 156 devices.end()) { 157 selected_device.clear(); 158 } 159 if (devices.empty()) { 160 device_preselected_ = false; 161 } else if (!device_preselected_) { 162 selected_device = devices.front(); 163 device_preselected_ = true; 164 } 165 context_.SetString(kContextKeySelectedDevice, selected_device); 166 context_.SetBoolean(kContextKeyControlsDisabled, selected_device.empty()); 167 CommitContextChanges(); 168} 169 170void ControllerPairingScreen::OnActorDestroyed( 171 ControllerPairingScreenActor* actor) { 172 if (actor_ == actor) 173 actor_ = NULL; 174} 175 176// Overridden from ControllerPairingView::Delegate: 177void ControllerPairingScreen::OnUserActed(const std::string& action) { 178 if (context_.GetBoolean(kContextKeyControlsDisabled)) { 179 LOG(WARNING) << "User acted, but controls are disabled. Ignoring."; 180 return; 181 } 182 bool disable_controls = true; 183 if (action == kActionChooseDevice) { 184 std::string selectedDevice = context_.GetString(kContextKeySelectedDevice); 185 if (selectedDevice.empty()) 186 LOG(ERROR) << "Device was not selected."; 187 else 188 controller_->ChooseDeviceForPairing(selectedDevice); 189 } else if (action == kActionRepeatDiscovery) { 190 controller_->RepeatDiscovery(); 191 } else if (action == kActionAcceptCode) { 192 controller_->SetConfirmationCodeIsCorrect(true); 193 } else if (action == kActionRejectCode) { 194 controller_->SetConfirmationCodeIsCorrect(false); 195 } else if (action == kActionProceedToAuthentication) { 196 context_.SetString(kContextKeyPage, kPageAuthentication); 197 disable_controls = false; 198 } else if (action == kActionEnroll) { 199 const std::string account_id = 200 gaia::SanitizeEmail(context_.GetString(kContextKeyAccountId)); 201 const std::string domain(gaia::ExtractDomainName(account_id)); 202 context_.SetString(kContextKeyEnrollmentDomain, domain); 203 } else if (action == kActionStartSession) { 204 controller_->StartSession(); 205 } 206 context_.SetBoolean(kContextKeyControlsDisabled, disable_controls); 207 CommitContextChanges(); 208} 209 210void ControllerPairingScreen::OnScreenContextChanged( 211 const base::DictionaryValue& diff) { 212 std::vector<std::string> changedKeys; 213 context_.ApplyChanges(diff, &changedKeys); 214 for (std::vector<std::string>::const_iterator key = changedKeys.begin(); 215 key != changedKeys.end(); 216 ++key) { 217 if (*key == kContextKeySelectedDevice) { 218 context_.SetBoolean(kContextKeyControlsDisabled, 219 context_.GetString(*key).empty()); 220 CommitContextChanges(); 221 } 222 } 223} 224 225} // namespace chromeos 226