root/chrome/browser/chromeos/login/enrollment/enrollment_screen.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. UMA
  2. weak_ptr_factory_
  3. SetParameters
  4. PrepareToShow
  5. Show
  6. Hide
  7. GetName
  8. OnLoginDone
  9. OnAuthError
  10. OnOAuthTokenAvailable
  11. OnRetry
  12. OnCancel
  13. OnConfirmationClosed
  14. RegisterForDevicePolicy
  15. ReportEnrollmentStatus
  16. UMAFailure
  17. ShowSigninScreen

// Copyright (c) 2012 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/enrollment_screen.h"

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/login/login_utils.h"
#include "chrome/browser/chromeos/login/screens/screen_observer.h"
#include "chrome/browser/chromeos/login/startup_utils.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/browser/chromeos/policy/auto_enrollment_client.h"
#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
#include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h"
#include "chromeos/dbus/cryptohome_client.h"
#include "chromeos/dbus/dbus_method_call_status.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/session_manager_client.h"
#include "components/policy/core/common/cloud/enterprise_metrics.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "google_apis/gaia/google_service_auth_error.h"

namespace chromeos {

namespace {

void UMA(int sample) {
  UMA_HISTOGRAM_ENUMERATION(policy::kMetricEnrollment,
                            sample,
                            policy::kMetricEnrollmentSize);
}

}  // namespace

EnrollmentScreen::EnrollmentScreen(
    ScreenObserver* observer,
    EnrollmentScreenActor* actor)
    : WizardScreen(observer),
      actor_(actor),
      enrollment_mode_(EnrollmentScreenActor::ENROLLMENT_MODE_MANUAL),
      enrollment_failed_once_(false),
      lockbox_init_duration_(0),
      weak_ptr_factory_(this) {
  // Init the TPM if it has not been done until now (in debug build we might
  // have not done that yet).
  DBusThreadManager::Get()->GetCryptohomeClient()->TpmCanAttemptOwnership(
      EmptyVoidDBusMethodCallback());
}

EnrollmentScreen::~EnrollmentScreen() {}

void EnrollmentScreen::SetParameters(
    EnrollmentScreenActor::EnrollmentMode enrollment_mode,
    const std::string& management_domain,
    const std::string& user) {
  enrollment_mode_ = enrollment_mode;
  user_ = user.empty() ? user : gaia::CanonicalizeEmail(user);
  actor_->SetParameters(this, enrollment_mode_, management_domain);
}

void EnrollmentScreen::PrepareToShow() {
  actor_->PrepareToShow();
}

void EnrollmentScreen::Show() {
  if (is_auto_enrollment() && !enrollment_failed_once_) {
    actor_->Show();
    UMA(policy::kMetricEnrollmentAutoStarted);
    actor_->ShowEnrollmentSpinnerScreen();
    actor_->FetchOAuthToken();
  } else {
    actor_->ResetAuth(base::Bind(&EnrollmentScreen::ShowSigninScreen,
                                 weak_ptr_factory_.GetWeakPtr()));
  }
}

void EnrollmentScreen::Hide() {
  actor_->Hide();
  weak_ptr_factory_.InvalidateWeakPtrs();
}

std::string EnrollmentScreen::GetName() const {
  return WizardController::kEnrollmentScreenName;
}

void EnrollmentScreen::OnLoginDone(const std::string& user) {
  user_ = gaia::CanonicalizeEmail(user);

  UMA(is_auto_enrollment() ? policy::kMetricEnrollmentAutoRetried
                           : policy::kMetricEnrollmentStarted);

  actor_->ShowEnrollmentSpinnerScreen();
  actor_->FetchOAuthToken();
}

void EnrollmentScreen::OnAuthError(
    const GoogleServiceAuthError& error) {
  enrollment_failed_once_ = true;
  actor_->ShowAuthError(error);

  switch (error.state()) {
    case GoogleServiceAuthError::NONE:
    case GoogleServiceAuthError::CAPTCHA_REQUIRED:
    case GoogleServiceAuthError::TWO_FACTOR:
    case GoogleServiceAuthError::HOSTED_NOT_ALLOWED:
    case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS:
    case GoogleServiceAuthError::REQUEST_CANCELED:
    case GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE:
    case GoogleServiceAuthError::SERVICE_ERROR:
      UMAFailure(policy::kMetricEnrollmentLoginFailed);
      LOG(ERROR) << "Auth error " << error.state();
      return;
    case GoogleServiceAuthError::USER_NOT_SIGNED_UP:
    case GoogleServiceAuthError::ACCOUNT_DELETED:
    case GoogleServiceAuthError::ACCOUNT_DISABLED:
      UMAFailure(policy::kMetricEnrollmentNotSupported);
      LOG(ERROR) << "Account error " << error.state();
      return;
    case GoogleServiceAuthError::CONNECTION_FAILED:
    case GoogleServiceAuthError::SERVICE_UNAVAILABLE:
      UMAFailure(policy::kMetricEnrollmentNetworkFailed);
      LOG(WARNING) << "Network error " << error.state();
      return;
    case GoogleServiceAuthError::NUM_STATES:
      break;
  }

  NOTREACHED();
  UMAFailure(policy::kMetricEnrollmentOtherFailed);
}

void EnrollmentScreen::OnOAuthTokenAvailable(
    const std::string& token) {
  RegisterForDevicePolicy(token);
}

void EnrollmentScreen::OnRetry() {
  actor_->ResetAuth(base::Bind(&EnrollmentScreen::ShowSigninScreen,
                               weak_ptr_factory_.GetWeakPtr()));
}

void EnrollmentScreen::OnCancel() {
  if (enrollment_mode_ == EnrollmentScreenActor::ENROLLMENT_MODE_FORCED) {
    actor_->ResetAuth(
        base::Bind(&ScreenObserver::OnExit,
                   base::Unretained(get_screen_observer()),
                   ScreenObserver::ENTERPRISE_ENROLLMENT_BACK));
    return;
  }

  if (is_auto_enrollment())
    policy::AutoEnrollmentClient::CancelAutoEnrollment();
  UMA(is_auto_enrollment() ? policy::kMetricEnrollmentAutoCancelled
                           : policy::kMetricEnrollmentCancelled);
  actor_->ResetAuth(
      base::Bind(&ScreenObserver::OnExit,
                 base::Unretained(get_screen_observer()),
                 ScreenObserver::ENTERPRISE_ENROLLMENT_COMPLETED));
}

void EnrollmentScreen::OnConfirmationClosed() {
  // If the machine has been put in KIOSK mode we have to restart the session
  // here to go in the proper KIOSK mode login screen.
  policy::BrowserPolicyConnectorChromeOS* connector =
      g_browser_process->platform_part()->browser_policy_connector_chromeos();
  if (connector->GetDeviceMode() == policy::DEVICE_MODE_RETAIL_KIOSK) {
    DBusThreadManager::Get()->GetSessionManagerClient()->StopSession();
    return;
  }

  if (is_auto_enrollment() &&
      !enrollment_failed_once_ &&
      !user_.empty() &&
      LoginUtils::IsWhitelisted(user_, NULL)) {
    actor_->ShowLoginSpinnerScreen();
    get_screen_observer()->OnExit(
        ScreenObserver::ENTERPRISE_AUTO_MAGIC_ENROLLMENT_COMPLETED);
  } else {
    actor_->ResetAuth(
        base::Bind(&ScreenObserver::OnExit,
                   base::Unretained(get_screen_observer()),
                   ScreenObserver::ENTERPRISE_ENROLLMENT_COMPLETED));
  }
}

void EnrollmentScreen::RegisterForDevicePolicy(
    const std::string& token) {
  policy::BrowserPolicyConnectorChromeOS* connector =
      g_browser_process->platform_part()->browser_policy_connector_chromeos();
  if (connector->IsEnterpriseManaged() &&
      connector->GetEnterpriseDomain() != gaia::ExtractDomainName(user_)) {
    LOG(ERROR) << "Trying to re-enroll to a different domain than "
               << connector->GetEnterpriseDomain();
    UMAFailure(policy::kMetricEnrollmentWrongUserError);
    actor_->ShowUIError(
        EnrollmentScreenActor::UI_ERROR_DOMAIN_MISMATCH);
    return;
  }

  policy::DeviceCloudPolicyManagerChromeOS::AllowedDeviceModes device_modes;
  device_modes[policy::DEVICE_MODE_ENTERPRISE] = true;
  device_modes[policy::DEVICE_MODE_RETAIL_KIOSK] =
      enrollment_mode_ == EnrollmentScreenActor::ENROLLMENT_MODE_MANUAL;
  connector->ScheduleServiceInitialization(0);
  connector->GetDeviceCloudPolicyManager()->StartEnrollment(
      token, is_auto_enrollment(), device_modes,
      base::Bind(&EnrollmentScreen::ReportEnrollmentStatus,
                 weak_ptr_factory_.GetWeakPtr()));
}

void EnrollmentScreen::ReportEnrollmentStatus(
    policy::EnrollmentStatus status) {
  bool success = status.status() == policy::EnrollmentStatus::STATUS_SUCCESS;
  enrollment_failed_once_ |= !success;
  actor_->ShowEnrollmentStatus(status);

  switch (status.status()) {
    case policy::EnrollmentStatus::STATUS_SUCCESS:
      StartupUtils::MarkDeviceRegistered();
      UMA(is_auto_enrollment() ? policy::kMetricEnrollmentAutoOK
                               : policy::kMetricEnrollmentOK);
      return;
    case policy::EnrollmentStatus::STATUS_REGISTRATION_FAILED:
    case policy::EnrollmentStatus::STATUS_POLICY_FETCH_FAILED:
      switch (status.client_status()) {
        case policy::DM_STATUS_SUCCESS:
        case policy::DM_STATUS_REQUEST_INVALID:
        case policy::DM_STATUS_SERVICE_DEVICE_NOT_FOUND:
        case policy::DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID:
        case policy::DM_STATUS_SERVICE_ACTIVATION_PENDING:
        case policy::DM_STATUS_SERVICE_DEVICE_ID_CONFLICT:
        case policy::DM_STATUS_SERVICE_POLICY_NOT_FOUND:
          UMAFailure(policy::kMetricEnrollmentOtherFailed);
          return;
        case policy::DM_STATUS_REQUEST_FAILED:
        case policy::DM_STATUS_TEMPORARY_UNAVAILABLE:
        case policy::DM_STATUS_HTTP_STATUS_ERROR:
        case policy::DM_STATUS_RESPONSE_DECODING_ERROR:
          UMAFailure(policy::kMetricEnrollmentNetworkFailed);
          return;
        case policy::DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED:
          UMAFailure(policy::kMetricEnrollmentNotSupported);
          return;
        case policy::DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER:
          UMAFailure(policy::kMetricEnrollmentInvalidSerialNumber);
          return;
        case policy::DM_STATUS_SERVICE_MISSING_LICENSES:
          UMAFailure(policy::kMetricMissingLicensesError);
          return;
        case policy::DM_STATUS_SERVICE_DEPROVISIONED:
          UMAFailure(policy::kMetricEnrollmentDeprovisioned);
          return;
        case policy::DM_STATUS_SERVICE_DOMAIN_MISMATCH:
          UMAFailure(policy::kMetricEnrollmentDomainMismatch);
          return;
      }
      break;
    case policy::EnrollmentStatus::STATUS_REGISTRATION_BAD_MODE:
      UMAFailure(policy::kMetricEnrollmentInvalidEnrollmentMode);
      return;
    case policy::EnrollmentStatus::STATUS_LOCK_TIMEOUT:
      UMAFailure(policy::kMetricLockboxTimeoutError);
      return;
    case policy::EnrollmentStatus::STATUS_LOCK_WRONG_USER:
      UMAFailure(policy::kMetricEnrollmentWrongUserError);
      return;
    case policy::EnrollmentStatus::STATUS_VALIDATION_FAILED:
    case policy::EnrollmentStatus::STATUS_STORE_ERROR:
    case policy::EnrollmentStatus::STATUS_LOCK_ERROR:
      UMAFailure(policy::kMetricEnrollmentOtherFailed);
      return;
    case policy::EnrollmentStatus::STATUS_ROBOT_AUTH_FETCH_FAILED:
      UMAFailure(policy::kMetricEnrollmentRobotAuthCodeFetchFailed);
      return;
    case policy::EnrollmentStatus::STATUS_ROBOT_REFRESH_FETCH_FAILED:
      UMAFailure(policy::kMetricEnrollmentRobotRefreshTokenFetchFailed);
      return;
    case policy::EnrollmentStatus::STATUS_ROBOT_REFRESH_STORE_FAILED:
      UMAFailure(policy::kMetricEnrollmentRobotRefreshTokenStoreFailed);
      return;
  }

  NOTREACHED();
  UMAFailure(policy::kMetricEnrollmentOtherFailed);
}

void EnrollmentScreen::UMAFailure(int sample) {
  if (is_auto_enrollment())
    sample = policy::kMetricEnrollmentAutoFailed;
  UMA(sample);
}

void EnrollmentScreen::ShowSigninScreen() {
  actor_->Show();
  actor_->ShowSigninScreen();
}

}  // namespace chromeos

/* [<][>][^][v][top][bottom][index][help] */