Home | History | Annotate | Download | only in enrollment
      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/enrollment/auto_enrollment_check_screen.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/bind_helpers.h"
      9 #include "base/command_line.h"
     10 #include "base/logging.h"
     11 #include "chrome/browser/chromeos/login/screen_manager.h"
     12 #include "chrome/browser/chromeos/login/screens/screen_observer.h"
     13 #include "chrome/browser/chromeos/login/wizard_controller.h"
     14 #include "chromeos/chromeos_switches.h"
     15 #include "chromeos/network/network_state.h"
     16 #include "chromeos/network/network_state_handler.h"
     17 
     18 namespace chromeos {
     19 
     20 // static
     21 AutoEnrollmentCheckScreen* AutoEnrollmentCheckScreen::Get(
     22     ScreenManager* manager) {
     23   return static_cast<AutoEnrollmentCheckScreen*>(
     24       manager->GetScreen(WizardController::kAutoEnrollmentCheckScreenName));
     25 }
     26 
     27 AutoEnrollmentCheckScreen::AutoEnrollmentCheckScreen(
     28     ScreenObserver* observer,
     29     AutoEnrollmentCheckScreenActor* actor)
     30     : WizardScreen(observer),
     31       actor_(actor),
     32       captive_portal_status_(
     33           NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN),
     34       auto_enrollment_state_(policy::AUTO_ENROLLMENT_STATE_IDLE) {
     35   if (actor_)
     36     actor_->SetDelegate(this);
     37 }
     38 
     39 AutoEnrollmentCheckScreen::~AutoEnrollmentCheckScreen() {
     40   NetworkPortalDetector::Get()->RemoveObserver(this);
     41   if (actor_)
     42     actor_->SetDelegate(NULL);
     43 }
     44 
     45 void AutoEnrollmentCheckScreen::Start() {
     46   if (!IsStartNeeded())
     47     return;
     48 
     49   // Make sure the auto-enrollment client is running.
     50   auto_enrollment_controller_->Start();
     51 
     52   auto_enrollment_progress_subscription_ =
     53       auto_enrollment_controller_->RegisterProgressCallback(
     54           base::Bind(
     55               &AutoEnrollmentCheckScreen::OnAutoEnrollmentCheckProgressed,
     56               base::Unretained(this)));
     57   auto_enrollment_state_ = auto_enrollment_controller_->state();
     58 
     59   // NB: AddAndFireObserver below call back into OnPortalDetectionCompleted.
     60   // This guarantees that the UI gets synced to current state.
     61   NetworkPortalDetector* portal_detector = NetworkPortalDetector::Get();
     62   portal_detector->StartDetectionIfIdle();
     63   portal_detector->AddAndFireObserver(this);
     64 }
     65 
     66 bool AutoEnrollmentCheckScreen::IsStartNeeded() {
     67   // Check that forced reenrollment is wanted and if the check is needed or we
     68   // already know the outcome.
     69   if (AutoEnrollmentController::GetMode() !=
     70       AutoEnrollmentController::MODE_FORCED_RE_ENROLLMENT ||
     71       auto_enrollment_state_ ==
     72       policy::AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT ||
     73       auto_enrollment_state_ == policy::AUTO_ENROLLMENT_STATE_NO_ENROLLMENT) {
     74     SignalCompletion();
     75     return false;
     76   }
     77   return true;
     78 }
     79 
     80 void AutoEnrollmentCheckScreen::PrepareToShow() {
     81 }
     82 
     83 void AutoEnrollmentCheckScreen::Show() {
     84   if (IsStartNeeded()) {
     85     Start();
     86     if (actor_)
     87       actor_->Show();
     88   }
     89 }
     90 
     91 void AutoEnrollmentCheckScreen::Hide() {
     92 }
     93 
     94 std::string AutoEnrollmentCheckScreen::GetName() const {
     95   return WizardController::kAutoEnrollmentCheckScreenName;
     96 }
     97 
     98 void AutoEnrollmentCheckScreen::OnExit() {
     99   get_screen_observer()->OnExit(
    100       ScreenObserver::ENTERPRISE_AUTO_ENROLLMENT_CHECK_COMPLETED);
    101 }
    102 
    103 void AutoEnrollmentCheckScreen::OnActorDestroyed(
    104     AutoEnrollmentCheckScreenActor* actor) {
    105   if (actor_ == actor)
    106     actor_ = NULL;
    107 }
    108 
    109 void AutoEnrollmentCheckScreen::OnPortalDetectionCompleted(
    110     const NetworkState* /* network */,
    111     const NetworkPortalDetector::CaptivePortalState& state) {
    112   UpdateState(state.status, auto_enrollment_state_);
    113 }
    114 
    115 void AutoEnrollmentCheckScreen::OnAutoEnrollmentCheckProgressed(
    116     policy::AutoEnrollmentState state) {
    117   UpdateState(captive_portal_status_, state);
    118 }
    119 
    120 void AutoEnrollmentCheckScreen::UpdateState(
    121     NetworkPortalDetector::CaptivePortalStatus new_captive_portal_status,
    122     policy::AutoEnrollmentState new_auto_enrollment_state) {
    123   // Configure the error screen to show the approriate error message.
    124   if (!UpdateCaptivePortalStatus(new_captive_portal_status))
    125     UpdateAutoEnrollmentState(new_auto_enrollment_state);
    126 
    127   // Update the connecting indicator.
    128   ErrorScreen* error_screen = get_screen_observer()->GetErrorScreen();
    129   error_screen->ShowConnectingIndicator(
    130       new_auto_enrollment_state == policy::AUTO_ENROLLMENT_STATE_PENDING);
    131 
    132   // Determine whether a retry is in order.
    133   bool retry = (new_captive_portal_status ==
    134                 NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE) &&
    135                (captive_portal_status_ !=
    136                 NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE);
    137 
    138   // Save the new state.
    139   captive_portal_status_ = new_captive_portal_status;
    140   auto_enrollment_state_ = new_auto_enrollment_state;
    141 
    142   // Check whether a decision got made.
    143   switch (new_auto_enrollment_state) {
    144     case policy::AUTO_ENROLLMENT_STATE_IDLE:
    145       NOTREACHED();
    146       // fall through.
    147     case policy::AUTO_ENROLLMENT_STATE_PENDING:
    148     case policy::AUTO_ENROLLMENT_STATE_CONNECTION_ERROR:
    149       break;
    150     case policy::AUTO_ENROLLMENT_STATE_SERVER_ERROR:
    151       // Server errors don't block OOBE.
    152     case policy::AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT:
    153     case policy::AUTO_ENROLLMENT_STATE_NO_ENROLLMENT:
    154       // Decision made, ready to proceed.
    155       SignalCompletion();
    156       return;
    157   }
    158 
    159   // Retry if applicable. This is last so eventual callbacks find consistent
    160   // state.
    161   if (retry)
    162     auto_enrollment_controller_->Retry();
    163 }
    164 
    165 bool AutoEnrollmentCheckScreen::UpdateCaptivePortalStatus(
    166     NetworkPortalDetector::CaptivePortalStatus new_captive_portal_status) {
    167   switch (new_captive_portal_status) {
    168     case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN:
    169     case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE:
    170       return false;
    171     case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE:
    172       ShowErrorScreen(ErrorScreen::ERROR_STATE_OFFLINE);
    173       return true;
    174     case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL:
    175       ShowErrorScreen(ErrorScreen::ERROR_STATE_PORTAL);
    176       if (captive_portal_status_ != new_captive_portal_status)
    177         get_screen_observer()->GetErrorScreen()->FixCaptivePortal();
    178       return true;
    179     case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED:
    180       ShowErrorScreen(ErrorScreen::ERROR_STATE_PROXY);
    181       return true;
    182     case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT:
    183       NOTREACHED() << "Bad status: CAPTIVE_PORTAL_STATUS_COUNT";
    184       return false;
    185   }
    186 
    187   // Return is required to avoid compiler warning.
    188   NOTREACHED() << "Bad status " << new_captive_portal_status;
    189   return false;
    190 }
    191 
    192 bool AutoEnrollmentCheckScreen::UpdateAutoEnrollmentState(
    193     policy::AutoEnrollmentState new_auto_enrollment_state) {
    194   switch (new_auto_enrollment_state) {
    195     case policy::AUTO_ENROLLMENT_STATE_IDLE:
    196       // The client should have been started already.
    197       NOTREACHED();
    198       return false;
    199     case policy::AUTO_ENROLLMENT_STATE_PENDING:
    200     case policy::AUTO_ENROLLMENT_STATE_SERVER_ERROR:
    201     case policy::AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT:
    202     case policy::AUTO_ENROLLMENT_STATE_NO_ENROLLMENT:
    203       return false;
    204     case policy::AUTO_ENROLLMENT_STATE_CONNECTION_ERROR:
    205       ShowErrorScreen(ErrorScreen::ERROR_STATE_OFFLINE);
    206       return true;
    207   }
    208 
    209   // Return is required to avoid compiler warning.
    210   NOTREACHED() << "bad state " << new_auto_enrollment_state;
    211   return false;
    212 }
    213 
    214 void AutoEnrollmentCheckScreen::ShowErrorScreen(
    215     ErrorScreen::ErrorState error_state) {
    216   const NetworkState* network =
    217       NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
    218   ErrorScreen* error_screen = get_screen_observer()->GetErrorScreen();
    219   error_screen->SetUIState(ErrorScreen::UI_STATE_AUTO_ENROLLMENT_ERROR);
    220   error_screen->AllowGuestSignin(true);
    221   error_screen->SetErrorState(error_state,
    222                               network ? network->name() : std::string());
    223   get_screen_observer()->ShowErrorScreen();
    224 }
    225 
    226 void AutoEnrollmentCheckScreen::SignalCompletion() {
    227   NetworkPortalDetector::Get()->RemoveObserver(this);
    228   auto_enrollment_progress_subscription_.reset();
    229   get_screen_observer()->OnExit(
    230       ScreenObserver::ENTERPRISE_AUTO_ENROLLMENT_CHECK_COMPLETED);
    231 }
    232 
    233 }  // namespace chromeos
    234