Home | History | Annotate | Download | only in screens
      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 
     12 using namespace chromeos::controller_pairing;
     13 using namespace pairing_chromeos;
     14 
     15 namespace chromeos {
     16 
     17 ControllerPairingScreen::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 
     30 ControllerPairingScreen::~ControllerPairingScreen() {
     31   if (actor_)
     32     actor_->SetDelegate(NULL);
     33   controller_->RemoveObserver(this);
     34 }
     35 
     36 void 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 
     45 bool 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 
     53 void ControllerPairingScreen::PrepareToShow() {
     54 }
     55 
     56 void ControllerPairingScreen::Show() {
     57   if (actor_)
     58     actor_->Show();
     59   controller_->StartPairing();
     60 }
     61 
     62 void ControllerPairingScreen::Hide() {
     63   if (actor_)
     64     actor_->Hide();
     65 }
     66 
     67 std::string ControllerPairingScreen::GetName() const {
     68   return WizardController::kControllerPairingScreenName;
     69 }
     70 
     71 // Overridden from ControllerPairingController::Observer:
     72 void 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 
    144 void 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 
    170 void ControllerPairingScreen::OnActorDestroyed(
    171     ControllerPairingScreenActor* actor) {
    172   if (actor_ == actor)
    173     actor_ = NULL;
    174 }
    175 
    176 // Overridden from ControllerPairingView::Delegate:
    177 void 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 
    210 void 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