Home | History | Annotate | Download | only in enrollment
      1 // Copyright (c) 2012 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/enrollment_screen.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/bind_helpers.h"
      9 #include "base/logging.h"
     10 #include "base/message_loop/message_loop.h"
     11 #include "base/metrics/histogram.h"
     12 #include "chrome/browser/browser_process.h"
     13 #include "chrome/browser/chromeos/login/login_utils.h"
     14 #include "chrome/browser/chromeos/login/screens/screen_observer.h"
     15 #include "chrome/browser/chromeos/login/startup_utils.h"
     16 #include "chrome/browser/chromeos/login/wizard_controller.h"
     17 #include "chrome/browser/chromeos/policy/auto_enrollment_client.h"
     18 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
     19 #include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h"
     20 #include "chromeos/dbus/cryptohome_client.h"
     21 #include "chromeos/dbus/dbus_method_call_status.h"
     22 #include "chromeos/dbus/dbus_thread_manager.h"
     23 #include "chromeos/dbus/session_manager_client.h"
     24 #include "google_apis/gaia/gaia_auth_util.h"
     25 #include "google_apis/gaia/google_service_auth_error.h"
     26 
     27 namespace chromeos {
     28 
     29 EnrollmentScreen::EnrollmentScreen(
     30     ScreenObserver* observer,
     31     EnrollmentScreenActor* actor)
     32     : WizardScreen(observer),
     33       actor_(actor),
     34       enrollment_mode_(EnrollmentScreenActor::ENROLLMENT_MODE_MANUAL),
     35       enrollment_failed_once_(false),
     36       lockbox_init_duration_(0),
     37       weak_ptr_factory_(this) {
     38   // Init the TPM if it has not been done until now (in debug build we might
     39   // have not done that yet).
     40   DBusThreadManager::Get()->GetCryptohomeClient()->TpmCanAttemptOwnership(
     41       EmptyVoidDBusMethodCallback());
     42 }
     43 
     44 EnrollmentScreen::~EnrollmentScreen() {}
     45 
     46 void EnrollmentScreen::SetParameters(
     47     EnrollmentScreenActor::EnrollmentMode enrollment_mode,
     48     const std::string& management_domain,
     49     const std::string& user) {
     50   enrollment_mode_ = enrollment_mode;
     51   user_ = user.empty() ? user : gaia::CanonicalizeEmail(user);
     52   actor_->SetParameters(this, enrollment_mode_, management_domain);
     53 }
     54 
     55 void EnrollmentScreen::PrepareToShow() {
     56   actor_->PrepareToShow();
     57 }
     58 
     59 void EnrollmentScreen::Show() {
     60   if (is_auto_enrollment() && !enrollment_failed_once_) {
     61     actor_->Show();
     62     UMA(policy::kMetricEnrollmentAutoStarted);
     63     actor_->ShowEnrollmentSpinnerScreen();
     64     actor_->FetchOAuthToken();
     65   } else {
     66     UMA(policy::kMetricEnrollmentTriggered);
     67     actor_->ResetAuth(base::Bind(&EnrollmentScreen::ShowSigninScreen,
     68                                  weak_ptr_factory_.GetWeakPtr()));
     69   }
     70 }
     71 
     72 void EnrollmentScreen::Hide() {
     73   actor_->Hide();
     74   weak_ptr_factory_.InvalidateWeakPtrs();
     75 }
     76 
     77 std::string EnrollmentScreen::GetName() const {
     78   return WizardController::kEnrollmentScreenName;
     79 }
     80 
     81 void EnrollmentScreen::OnLoginDone(const std::string& user) {
     82   user_ = gaia::CanonicalizeEmail(user);
     83 
     84   if (is_auto_enrollment())
     85     UMA(policy::kMetricEnrollmentAutoRetried);
     86   else if (enrollment_failed_once_)
     87     UMA(policy::kMetricEnrollmentRetried);
     88   else
     89     UMA(policy::kMetricEnrollmentStarted);
     90 
     91   actor_->ShowEnrollmentSpinnerScreen();
     92   actor_->FetchOAuthToken();
     93 }
     94 
     95 void EnrollmentScreen::OnAuthError(const GoogleServiceAuthError& error) {
     96   enrollment_failed_once_ = true;
     97   actor_->ShowAuthError(error);
     98 
     99   switch (error.state()) {
    100     case GoogleServiceAuthError::NONE:
    101     case GoogleServiceAuthError::CAPTCHA_REQUIRED:
    102     case GoogleServiceAuthError::TWO_FACTOR:
    103     case GoogleServiceAuthError::HOSTED_NOT_ALLOWED:
    104     case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS:
    105     case GoogleServiceAuthError::REQUEST_CANCELED:
    106     case GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE:
    107     case GoogleServiceAuthError::SERVICE_ERROR:
    108       UMAFailure(policy::kMetricEnrollmentLoginFailed);
    109       LOG(ERROR) << "Auth error " << error.state();
    110       return;
    111     case GoogleServiceAuthError::USER_NOT_SIGNED_UP:
    112     case GoogleServiceAuthError::ACCOUNT_DELETED:
    113     case GoogleServiceAuthError::ACCOUNT_DISABLED:
    114       UMAFailure(policy::kMetricEnrollmentNotSupported);
    115       LOG(ERROR) << "Account error " << error.state();
    116       return;
    117     case GoogleServiceAuthError::CONNECTION_FAILED:
    118     case GoogleServiceAuthError::SERVICE_UNAVAILABLE:
    119       UMAFailure(policy::kMetricEnrollmentNetworkFailed);
    120       LOG(WARNING) << "Network error " << error.state();
    121       return;
    122     case GoogleServiceAuthError::NUM_STATES:
    123       break;
    124   }
    125 
    126   NOTREACHED();
    127   UMAFailure(policy::kMetricEnrollmentOtherFailed);
    128 }
    129 
    130 void EnrollmentScreen::OnOAuthTokenAvailable(
    131     const std::string& token) {
    132   RegisterForDevicePolicy(token);
    133 }
    134 
    135 void EnrollmentScreen::OnRetry() {
    136   actor_->ResetAuth(base::Bind(&EnrollmentScreen::ShowSigninScreen,
    137                                weak_ptr_factory_.GetWeakPtr()));
    138 }
    139 
    140 void EnrollmentScreen::OnCancel() {
    141   if (enrollment_mode_ == EnrollmentScreenActor::ENROLLMENT_MODE_FORCED ||
    142       enrollment_mode_ == EnrollmentScreenActor::ENROLLMENT_MODE_RECOVERY) {
    143     actor_->ResetAuth(
    144         base::Bind(&ScreenObserver::OnExit,
    145                    base::Unretained(get_screen_observer()),
    146                    ScreenObserver::ENTERPRISE_ENROLLMENT_BACK));
    147     return;
    148   }
    149 
    150   if (is_auto_enrollment())
    151     policy::AutoEnrollmentClient::CancelAutoEnrollment();
    152   UMA(is_auto_enrollment() ? policy::kMetricEnrollmentAutoCancelled
    153                            : policy::kMetricEnrollmentCancelled);
    154   actor_->ResetAuth(
    155       base::Bind(&ScreenObserver::OnExit,
    156                  base::Unretained(get_screen_observer()),
    157                  ScreenObserver::ENTERPRISE_ENROLLMENT_COMPLETED));
    158 }
    159 
    160 void EnrollmentScreen::OnConfirmationClosed() {
    161   // If the machine has been put in KIOSK mode we have to restart the session
    162   // here to go in the proper KIOSK mode login screen.
    163   policy::BrowserPolicyConnectorChromeOS* connector =
    164       g_browser_process->platform_part()->browser_policy_connector_chromeos();
    165   if (connector->GetDeviceMode() == policy::DEVICE_MODE_RETAIL_KIOSK) {
    166     DBusThreadManager::Get()->GetSessionManagerClient()->StopSession();
    167     return;
    168   }
    169 
    170   if (is_auto_enrollment() &&
    171       !enrollment_failed_once_ &&
    172       !user_.empty() &&
    173       LoginUtils::IsWhitelisted(user_, NULL)) {
    174     actor_->ShowLoginSpinnerScreen();
    175     get_screen_observer()->OnExit(
    176         ScreenObserver::ENTERPRISE_AUTO_MAGIC_ENROLLMENT_COMPLETED);
    177   } else {
    178     actor_->ResetAuth(
    179         base::Bind(&ScreenObserver::OnExit,
    180                    base::Unretained(get_screen_observer()),
    181                    ScreenObserver::ENTERPRISE_ENROLLMENT_COMPLETED));
    182   }
    183 }
    184 
    185 void EnrollmentScreen::RegisterForDevicePolicy(
    186     const std::string& token) {
    187   policy::BrowserPolicyConnectorChromeOS* connector =
    188       g_browser_process->platform_part()->browser_policy_connector_chromeos();
    189   if (connector->IsEnterpriseManaged() &&
    190       connector->GetEnterpriseDomain() != gaia::ExtractDomainName(user_)) {
    191     LOG(ERROR) << "Trying to re-enroll to a different domain than "
    192                << connector->GetEnterpriseDomain();
    193     UMAFailure(policy::kMetricEnrollmentWrongUserError);
    194     actor_->ShowUIError(
    195         EnrollmentScreenActor::UI_ERROR_DOMAIN_MISMATCH);
    196     return;
    197   }
    198 
    199   policy::DeviceCloudPolicyManagerChromeOS::AllowedDeviceModes device_modes;
    200   device_modes[policy::DEVICE_MODE_ENTERPRISE] = true;
    201   device_modes[policy::DEVICE_MODE_RETAIL_KIOSK] =
    202       enrollment_mode_ == EnrollmentScreenActor::ENROLLMENT_MODE_MANUAL;
    203   connector->ScheduleServiceInitialization(0);
    204   connector->GetDeviceCloudPolicyManager()->StartEnrollment(
    205       token, is_auto_enrollment(), device_modes,
    206       base::Bind(&EnrollmentScreen::ReportEnrollmentStatus,
    207                  weak_ptr_factory_.GetWeakPtr()));
    208 }
    209 
    210 void EnrollmentScreen::ShowEnrollmentStatusOnSuccess(
    211     const policy::EnrollmentStatus& status) {
    212   actor_->ShowEnrollmentStatus(status);
    213   StartupUtils::MarkOobeCompleted();
    214 }
    215 
    216 void EnrollmentScreen::ReportEnrollmentStatus(
    217     policy::EnrollmentStatus status) {
    218   bool success = status.status() == policy::EnrollmentStatus::STATUS_SUCCESS;
    219   enrollment_failed_once_ |= !success;
    220   if (status.status() == policy::EnrollmentStatus::STATUS_SUCCESS) {
    221     StartupUtils::MarkDeviceRegistered(
    222         base::Bind(&EnrollmentScreen::ShowEnrollmentStatusOnSuccess,
    223                    weak_ptr_factory_.GetWeakPtr(),
    224                    status));
    225     UMA(is_auto_enrollment() ? policy::kMetricEnrollmentAutoOK
    226                              : policy::kMetricEnrollmentOK);
    227     return;
    228   }
    229   actor_->ShowEnrollmentStatus(status);
    230 
    231   switch (status.status()) {
    232     case policy::EnrollmentStatus::STATUS_REGISTRATION_FAILED:
    233     case policy::EnrollmentStatus::STATUS_POLICY_FETCH_FAILED:
    234       switch (status.client_status()) {
    235         case policy::DM_STATUS_SUCCESS:
    236         case policy::DM_STATUS_REQUEST_INVALID:
    237         case policy::DM_STATUS_SERVICE_DEVICE_NOT_FOUND:
    238         case policy::DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID:
    239         case policy::DM_STATUS_SERVICE_ACTIVATION_PENDING:
    240         case policy::DM_STATUS_SERVICE_DEVICE_ID_CONFLICT:
    241         case policy::DM_STATUS_SERVICE_POLICY_NOT_FOUND:
    242           UMAFailure(policy::kMetricEnrollmentOtherFailed);
    243           return;
    244         case policy::DM_STATUS_REQUEST_FAILED:
    245         case policy::DM_STATUS_TEMPORARY_UNAVAILABLE:
    246         case policy::DM_STATUS_HTTP_STATUS_ERROR:
    247         case policy::DM_STATUS_RESPONSE_DECODING_ERROR:
    248           UMAFailure(policy::kMetricEnrollmentNetworkFailed);
    249           return;
    250         case policy::DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED:
    251           UMAFailure(policy::kMetricEnrollmentNotSupported);
    252           return;
    253         case policy::DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER:
    254           UMAFailure(policy::kMetricEnrollmentInvalidSerialNumber);
    255           return;
    256         case policy::DM_STATUS_SERVICE_MISSING_LICENSES:
    257           UMAFailure(policy::kMetricMissingLicensesError);
    258           return;
    259         case policy::DM_STATUS_SERVICE_DEPROVISIONED:
    260           UMAFailure(policy::kMetricEnrollmentDeprovisioned);
    261           return;
    262         case policy::DM_STATUS_SERVICE_DOMAIN_MISMATCH:
    263           UMAFailure(policy::kMetricEnrollmentDomainMismatch);
    264           return;
    265       }
    266       break;
    267     case policy::EnrollmentStatus::STATUS_REGISTRATION_BAD_MODE:
    268       UMAFailure(policy::kMetricEnrollmentInvalidEnrollmentMode);
    269       return;
    270     case policy::EnrollmentStatus::STATUS_LOCK_TIMEOUT:
    271       UMAFailure(policy::kMetricLockboxTimeoutError);
    272       return;
    273     case policy::EnrollmentStatus::STATUS_LOCK_WRONG_USER:
    274       UMAFailure(policy::kMetricEnrollmentWrongUserError);
    275       return;
    276     case policy::EnrollmentStatus::STATUS_NO_STATE_KEYS:
    277     case policy::EnrollmentStatus::STATUS_VALIDATION_FAILED:
    278     case policy::EnrollmentStatus::STATUS_STORE_ERROR:
    279     case policy::EnrollmentStatus::STATUS_LOCK_ERROR:
    280       UMAFailure(policy::kMetricEnrollmentOtherFailed);
    281       return;
    282     case policy::EnrollmentStatus::STATUS_ROBOT_AUTH_FETCH_FAILED:
    283       UMAFailure(policy::kMetricEnrollmentRobotAuthCodeFetchFailed);
    284       return;
    285     case policy::EnrollmentStatus::STATUS_ROBOT_REFRESH_FETCH_FAILED:
    286       UMAFailure(policy::kMetricEnrollmentRobotRefreshTokenFetchFailed);
    287       return;
    288     case policy::EnrollmentStatus::STATUS_ROBOT_REFRESH_STORE_FAILED:
    289       UMAFailure(policy::kMetricEnrollmentRobotRefreshTokenStoreFailed);
    290       return;
    291     case policy::EnrollmentStatus::STATUS_SUCCESS:
    292       NOTREACHED();
    293       return;
    294   }
    295 
    296   NOTREACHED();
    297   UMAFailure(policy::kMetricEnrollmentOtherFailed);
    298 }
    299 
    300 void EnrollmentScreen::UMA(policy::MetricEnrollment sample) {
    301   if (enrollment_mode_ == EnrollmentScreenActor::ENROLLMENT_MODE_RECOVERY) {
    302     UMA_HISTOGRAM_ENUMERATION(policy::kMetricEnrollmentRecovery, sample,
    303                               policy::kMetricEnrollmentSize);
    304   } else {
    305     UMA_HISTOGRAM_ENUMERATION(policy::kMetricEnrollment, sample,
    306                               policy::kMetricEnrollmentSize);
    307   }
    308 }
    309 
    310 void EnrollmentScreen::UMAFailure(policy::MetricEnrollment sample) {
    311   if (is_auto_enrollment())
    312     sample = policy::kMetricEnrollmentAutoFailed;
    313   UMA(sample);
    314 }
    315 
    316 void EnrollmentScreen::ShowSigninScreen() {
    317   actor_->Show();
    318   actor_->ShowSigninScreen();
    319 }
    320 
    321 }  // namespace chromeos
    322