blob: 87f10acfa36e2c778bc2e9da115852c5c99572a4 [file] [log] [blame]
// 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 "chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "chrome/browser/chromeos/login/error_screens_histogram_helper.h"
#include "chrome/browser/chromeos/login/screen_manager.h"
#include "chrome/browser/chromeos/login/screens/screen_observer.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chromeos/chromeos_switches.h"
#include "chromeos/network/network_state.h"
#include "chromeos/network/network_state_handler.h"
namespace chromeos {
// static
AutoEnrollmentCheckScreen* AutoEnrollmentCheckScreen::Get(
ScreenManager* manager) {
return static_cast<AutoEnrollmentCheckScreen*>(
manager->GetScreen(WizardController::kAutoEnrollmentCheckScreenName));
}
AutoEnrollmentCheckScreen::AutoEnrollmentCheckScreen(
ScreenObserver* observer,
AutoEnrollmentCheckScreenActor* actor)
: BaseScreen(observer),
actor_(actor),
captive_portal_status_(
NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN),
auto_enrollment_state_(policy::AUTO_ENROLLMENT_STATE_IDLE),
histogram_helper_(new ErrorScreensHistogramHelper("Enrollment")) {
if (actor_)
actor_->SetDelegate(this);
}
AutoEnrollmentCheckScreen::~AutoEnrollmentCheckScreen() {
NetworkPortalDetector::Get()->RemoveObserver(this);
if (actor_)
actor_->SetDelegate(NULL);
}
void AutoEnrollmentCheckScreen::Start() {
if (!IsStartNeeded())
return;
// Make sure the auto-enrollment client is running.
auto_enrollment_controller_->Start();
auto_enrollment_progress_subscription_ =
auto_enrollment_controller_->RegisterProgressCallback(
base::Bind(
&AutoEnrollmentCheckScreen::OnAutoEnrollmentCheckProgressed,
base::Unretained(this)));
auto_enrollment_state_ = auto_enrollment_controller_->state();
// NB: AddAndFireObserver below call back into OnPortalDetectionCompleted.
// This guarantees that the UI gets synced to current state.
NetworkPortalDetector* portal_detector = NetworkPortalDetector::Get();
portal_detector->StartDetectionIfIdle();
portal_detector->AddAndFireObserver(this);
}
bool AutoEnrollmentCheckScreen::IsStartNeeded() {
// Check that forced reenrollment is wanted and if the check is needed or we
// already know the outcome.
if (AutoEnrollmentController::GetMode() !=
AutoEnrollmentController::MODE_FORCED_RE_ENROLLMENT ||
auto_enrollment_state_ ==
policy::AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT ||
auto_enrollment_state_ == policy::AUTO_ENROLLMENT_STATE_NO_ENROLLMENT) {
SignalCompletion();
return false;
}
return true;
}
void AutoEnrollmentCheckScreen::PrepareToShow() {
}
void AutoEnrollmentCheckScreen::Show() {
if (IsStartNeeded()) {
Start();
if (actor_)
actor_->Show();
histogram_helper_->OnScreenShow();
}
}
void AutoEnrollmentCheckScreen::Hide() {
}
std::string AutoEnrollmentCheckScreen::GetName() const {
return WizardController::kAutoEnrollmentCheckScreenName;
}
void AutoEnrollmentCheckScreen::OnExit() {
get_screen_observer()->OnExit(
ScreenObserver::ENTERPRISE_AUTO_ENROLLMENT_CHECK_COMPLETED);
}
void AutoEnrollmentCheckScreen::OnActorDestroyed(
AutoEnrollmentCheckScreenActor* actor) {
if (actor_ == actor)
actor_ = NULL;
}
void AutoEnrollmentCheckScreen::OnPortalDetectionCompleted(
const NetworkState* /* network */,
const NetworkPortalDetector::CaptivePortalState& state) {
UpdateState(state.status, auto_enrollment_state_);
}
void AutoEnrollmentCheckScreen::OnAutoEnrollmentCheckProgressed(
policy::AutoEnrollmentState state) {
UpdateState(captive_portal_status_, state);
}
void AutoEnrollmentCheckScreen::UpdateState(
NetworkPortalDetector::CaptivePortalStatus new_captive_portal_status,
policy::AutoEnrollmentState new_auto_enrollment_state) {
// Configure the error screen to show the approriate error message.
if (!UpdateCaptivePortalStatus(new_captive_portal_status))
UpdateAutoEnrollmentState(new_auto_enrollment_state);
// Update the connecting indicator.
ErrorScreen* error_screen = get_screen_observer()->GetErrorScreen();
error_screen->ShowConnectingIndicator(
new_auto_enrollment_state == policy::AUTO_ENROLLMENT_STATE_PENDING);
// Determine whether a retry is in order.
bool retry = (new_captive_portal_status ==
NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE) &&
(captive_portal_status_ !=
NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE);
// Save the new state.
captive_portal_status_ = new_captive_portal_status;
auto_enrollment_state_ = new_auto_enrollment_state;
// Check whether a decision got made.
switch (new_auto_enrollment_state) {
case policy::AUTO_ENROLLMENT_STATE_IDLE:
NOTREACHED();
// fall through.
case policy::AUTO_ENROLLMENT_STATE_PENDING:
case policy::AUTO_ENROLLMENT_STATE_CONNECTION_ERROR:
break;
case policy::AUTO_ENROLLMENT_STATE_SERVER_ERROR:
// Server errors don't block OOBE.
case policy::AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT:
case policy::AUTO_ENROLLMENT_STATE_NO_ENROLLMENT:
// Decision made, ready to proceed.
SignalCompletion();
return;
}
// Retry if applicable. This is last so eventual callbacks find consistent
// state.
if (retry)
auto_enrollment_controller_->Retry();
}
bool AutoEnrollmentCheckScreen::UpdateCaptivePortalStatus(
NetworkPortalDetector::CaptivePortalStatus new_captive_portal_status) {
switch (new_captive_portal_status) {
case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN:
case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE:
return false;
case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE:
ShowErrorScreen(ErrorScreen::ERROR_STATE_OFFLINE);
return true;
case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL:
ShowErrorScreen(ErrorScreen::ERROR_STATE_PORTAL);
if (captive_portal_status_ != new_captive_portal_status)
get_screen_observer()->GetErrorScreen()->FixCaptivePortal();
return true;
case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED:
ShowErrorScreen(ErrorScreen::ERROR_STATE_PROXY);
return true;
case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT:
NOTREACHED() << "Bad status: CAPTIVE_PORTAL_STATUS_COUNT";
return false;
}
// Return is required to avoid compiler warning.
NOTREACHED() << "Bad status " << new_captive_portal_status;
return false;
}
bool AutoEnrollmentCheckScreen::UpdateAutoEnrollmentState(
policy::AutoEnrollmentState new_auto_enrollment_state) {
switch (new_auto_enrollment_state) {
case policy::AUTO_ENROLLMENT_STATE_IDLE:
// The client should have been started already.
NOTREACHED();
return false;
case policy::AUTO_ENROLLMENT_STATE_PENDING:
case policy::AUTO_ENROLLMENT_STATE_SERVER_ERROR:
case policy::AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT:
case policy::AUTO_ENROLLMENT_STATE_NO_ENROLLMENT:
return false;
case policy::AUTO_ENROLLMENT_STATE_CONNECTION_ERROR:
ShowErrorScreen(ErrorScreen::ERROR_STATE_OFFLINE);
return true;
}
// Return is required to avoid compiler warning.
NOTREACHED() << "bad state " << new_auto_enrollment_state;
return false;
}
void AutoEnrollmentCheckScreen::ShowErrorScreen(
ErrorScreen::ErrorState error_state) {
const NetworkState* network =
NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
ErrorScreen* error_screen = get_screen_observer()->GetErrorScreen();
error_screen->SetUIState(ErrorScreen::UI_STATE_AUTO_ENROLLMENT_ERROR);
error_screen->AllowGuestSignin(true);
error_screen->SetErrorState(error_state,
network ? network->name() : std::string());
get_screen_observer()->ShowErrorScreen();
histogram_helper_->OnErrorShow(error_state);
}
void AutoEnrollmentCheckScreen::SignalCompletion() {
NetworkPortalDetector::Get()->RemoveObserver(this);
auto_enrollment_progress_subscription_.reset();
get_screen_observer()->OnExit(
ScreenObserver::ENTERPRISE_AUTO_ENROLLMENT_CHECK_COMPLETED);
}
} // namespace chromeos