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