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 "base/metrics/sparse_histogram.h" 13 #include "base/timer/elapsed_timer.h" 14 #include "chrome/browser/browser_process.h" 15 #include "chrome/browser/browser_process_platform_part.h" 16 #include "chrome/browser/chromeos/login/login_utils.h" 17 #include "chrome/browser/chromeos/login/screen_manager.h" 18 #include "chrome/browser/chromeos/login/screens/screen_observer.h" 19 #include "chrome/browser/chromeos/login/startup_utils.h" 20 #include "chrome/browser/chromeos/login/wizard_controller.h" 21 #include "chrome/browser/chromeos/policy/auto_enrollment_client.h" 22 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" 23 #include "chrome/browser/chromeos/policy/device_cloud_policy_initializer.h" 24 #include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h" 25 #include "chromeos/dbus/cryptohome_client.h" 26 #include "chromeos/dbus/dbus_method_call_status.h" 27 #include "chromeos/dbus/dbus_thread_manager.h" 28 #include "chromeos/dbus/session_manager_client.h" 29 #include "components/pairing/controller_pairing_controller.h" 30 #include "google_apis/gaia/gaia_auth_util.h" 31 #include "google_apis/gaia/google_service_auth_error.h" 32 #include "policy/proto/device_management_backend.pb.h" 33 34 using namespace pairing_chromeos; 35 36 // Do not change the UMA histogram parameters without renaming the histograms! 37 #define UMA_ENROLLMENT_TIME(histogram_name, elapsed_timer) \ 38 do { \ 39 UMA_HISTOGRAM_CUSTOM_TIMES( \ 40 (histogram_name), \ 41 (elapsed_timer)->Elapsed(), \ 42 base::TimeDelta::FromMilliseconds(100) /* min */, \ 43 base::TimeDelta::FromMinutes(15) /* max */, \ 44 100 /* bucket_count */); \ 45 } while (0) 46 47 namespace chromeos { 48 49 // static 50 EnrollmentScreen* EnrollmentScreen::Get(ScreenManager* manager) { 51 return static_cast<EnrollmentScreen*>( 52 manager->GetScreen(WizardController::kEnrollmentScreenName)); 53 } 54 55 EnrollmentScreen::EnrollmentScreen( 56 ScreenObserver* observer, 57 EnrollmentScreenActor* actor) 58 : WizardScreen(observer), 59 shark_controller_(NULL), 60 remora_controller_(NULL), 61 actor_(actor), 62 enrollment_mode_(EnrollmentScreenActor::ENROLLMENT_MODE_MANUAL), 63 enrollment_failed_once_(false), 64 remora_token_sent_(false), 65 lockbox_init_duration_(0), 66 weak_ptr_factory_(this) { 67 // Init the TPM if it has not been done until now (in debug build we might 68 // have not done that yet). 69 DBusThreadManager::Get()->GetCryptohomeClient()->TpmCanAttemptOwnership( 70 EmptyVoidDBusMethodCallback()); 71 } 72 73 EnrollmentScreen::~EnrollmentScreen() { 74 if (remora_controller_) 75 remora_controller_->RemoveObserver(this); 76 } 77 78 void EnrollmentScreen::SetParameters( 79 EnrollmentScreenActor::EnrollmentMode enrollment_mode, 80 const std::string& management_domain, 81 const std::string& user, 82 const std::string& auth_token, 83 pairing_chromeos::ControllerPairingController* shark_controller, 84 pairing_chromeos::HostPairingController* remora_controller) { 85 enrollment_mode_ = enrollment_mode; 86 user_ = user.empty() ? user : gaia::CanonicalizeEmail(user); 87 auth_token_ = auth_token; 88 shark_controller_ = shark_controller; 89 if (remora_controller_) 90 remora_controller_->RemoveObserver(this); 91 remora_controller_ = remora_controller; 92 if (remora_controller_) 93 remora_controller_->AddObserver(this); 94 actor_->SetParameters(this, enrollment_mode_, management_domain); 95 } 96 97 void EnrollmentScreen::PrepareToShow() { 98 actor_->PrepareToShow(); 99 } 100 101 void EnrollmentScreen::Show() { 102 if (is_auto_enrollment() && !enrollment_failed_once_) { 103 actor_->Show(); 104 UMA(policy::kMetricEnrollmentAutoStarted); 105 actor_->ShowEnrollmentSpinnerScreen(); 106 actor_->FetchOAuthToken(); 107 } else if (auth_token_.empty()) { 108 UMA(policy::kMetricEnrollmentTriggered); 109 actor_->ResetAuth(base::Bind(&EnrollmentScreen::ShowSigninScreen, 110 weak_ptr_factory_.GetWeakPtr())); 111 } else { 112 actor_->Show(); 113 actor_->ShowEnrollmentSpinnerScreen(); 114 OnOAuthTokenAvailable(auth_token_); 115 } 116 } 117 118 void EnrollmentScreen::Hide() { 119 actor_->Hide(); 120 weak_ptr_factory_.InvalidateWeakPtrs(); 121 } 122 123 std::string EnrollmentScreen::GetName() const { 124 return WizardController::kEnrollmentScreenName; 125 } 126 127 void EnrollmentScreen::PairingStageChanged(Stage new_stage) { 128 DCHECK(remora_controller_); 129 if (new_stage == HostPairingController::STAGE_FINISHED) { 130 remora_controller_->RemoveObserver(this); 131 remora_controller_ = NULL; 132 // TODO(zork): Check that this is the best exit status. crbug.com/412798 133 get_screen_observer()->OnExit( 134 WizardController::ENTERPRISE_AUTO_MAGIC_ENROLLMENT_COMPLETED); 135 } 136 } 137 138 void EnrollmentScreen::ConfigureHost(bool accepted_eula, 139 const std::string& lang, 140 const std::string& timezone, 141 bool send_reports, 142 const std::string& keyboard_layout) { 143 } 144 145 void EnrollmentScreen::EnrollHost(const std::string& auth_token) { 146 } 147 148 void EnrollmentScreen::OnLoginDone(const std::string& user) { 149 elapsed_timer_.reset(new base::ElapsedTimer()); 150 user_ = gaia::CanonicalizeEmail(user); 151 152 if (is_auto_enrollment()) 153 UMA(policy::kMetricEnrollmentAutoRestarted); 154 else if (enrollment_failed_once_) 155 UMA(policy::kMetricEnrollmentRestarted); 156 else 157 UMA(policy::kMetricEnrollmentStarted); 158 159 actor_->ShowEnrollmentSpinnerScreen(); 160 actor_->FetchOAuthToken(); 161 } 162 163 void EnrollmentScreen::OnAuthError(const GoogleServiceAuthError& error) { 164 switch (error.state()) { 165 case GoogleServiceAuthError::NONE: 166 case GoogleServiceAuthError::CAPTCHA_REQUIRED: 167 case GoogleServiceAuthError::TWO_FACTOR: 168 case GoogleServiceAuthError::HOSTED_NOT_ALLOWED: 169 case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS: 170 case GoogleServiceAuthError::REQUEST_CANCELED: 171 case GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE: 172 case GoogleServiceAuthError::SERVICE_ERROR: 173 UMAFailure(policy::kMetricEnrollmentLoginFailed); 174 LOG(ERROR) << "Auth error " << error.state(); 175 break; 176 case GoogleServiceAuthError::USER_NOT_SIGNED_UP: 177 UMAFailure(policy::kMetricEnrollmentAccountNotSignedUp); 178 LOG(ERROR) << "Account not signed up " << error.state(); 179 break; 180 case GoogleServiceAuthError::ACCOUNT_DELETED: 181 UMAFailure(policy::kMetricEnrollmentAccountDeleted); 182 LOG(ERROR) << "Account deleted " << error.state(); 183 break; 184 case GoogleServiceAuthError::ACCOUNT_DISABLED: 185 UMAFailure(policy::kMetricEnrollmentAccountDisabled); 186 LOG(ERROR) << "Account disabled " << error.state(); 187 break; 188 case GoogleServiceAuthError::CONNECTION_FAILED: 189 case GoogleServiceAuthError::SERVICE_UNAVAILABLE: 190 UMAFailure(policy::kMetricEnrollmentNetworkFailed); 191 LOG(WARNING) << "Network error " << error.state(); 192 break; 193 case GoogleServiceAuthError::NUM_STATES: 194 NOTREACHED(); 195 break; 196 } 197 198 enrollment_failed_once_ = true; 199 actor_->ShowAuthError(error); 200 } 201 202 void EnrollmentScreen::OnOAuthTokenAvailable(const std::string& token) { 203 VLOG(1) << "OnOAuthTokenAvailable " << token; 204 const bool is_shark = 205 g_browser_process->platform_part()->browser_policy_connector_chromeos()-> 206 GetDeviceCloudPolicyManager()->IsSharkRequisition(); 207 208 if (is_shark && !remora_token_sent_) { 209 // Fetch a second token for shark devices. 210 remora_token_sent_ = true; 211 SendEnrollmentAuthToken(token); 212 actor_->FetchOAuthToken(); 213 } else { 214 RegisterForDevicePolicy(token); 215 } 216 } 217 218 void EnrollmentScreen::OnRetry() { 219 actor_->ResetAuth(base::Bind(&EnrollmentScreen::ShowSigninScreen, 220 weak_ptr_factory_.GetWeakPtr())); 221 } 222 223 void EnrollmentScreen::OnCancel() { 224 UMA(is_auto_enrollment() ? policy::kMetricEnrollmentAutoCancelled 225 : policy::kMetricEnrollmentCancelled); 226 if (elapsed_timer_) 227 UMA_ENROLLMENT_TIME("Enterprise.EnrollmentTime.Cancel", elapsed_timer_); 228 if (enrollment_mode_ == EnrollmentScreenActor::ENROLLMENT_MODE_FORCED || 229 enrollment_mode_ == EnrollmentScreenActor::ENROLLMENT_MODE_RECOVERY) { 230 actor_->ResetAuth( 231 base::Bind(&ScreenObserver::OnExit, 232 base::Unretained(get_screen_observer()), 233 ScreenObserver::ENTERPRISE_ENROLLMENT_BACK)); 234 return; 235 } 236 237 if (is_auto_enrollment()) 238 policy::AutoEnrollmentClient::CancelAutoEnrollment(); 239 actor_->ResetAuth( 240 base::Bind(&ScreenObserver::OnExit, 241 base::Unretained(get_screen_observer()), 242 ScreenObserver::ENTERPRISE_ENROLLMENT_COMPLETED)); 243 } 244 245 void EnrollmentScreen::OnConfirmationClosed() { 246 // If the machine has been put in KIOSK mode we have to restart the session 247 // here to go in the proper KIOSK mode login screen. 248 policy::BrowserPolicyConnectorChromeOS* connector = 249 g_browser_process->platform_part()->browser_policy_connector_chromeos(); 250 if (connector->GetDeviceMode() == policy::DEVICE_MODE_RETAIL_KIOSK) { 251 DBusThreadManager::Get()->GetSessionManagerClient()->StopSession(); 252 return; 253 } 254 255 if (is_auto_enrollment() && 256 !enrollment_failed_once_ && 257 !user_.empty() && 258 LoginUtils::IsWhitelisted(user_, NULL)) { 259 actor_->ShowLoginSpinnerScreen(); 260 get_screen_observer()->OnExit( 261 ScreenObserver::ENTERPRISE_AUTO_MAGIC_ENROLLMENT_COMPLETED); 262 } else { 263 actor_->ResetAuth( 264 base::Bind(&ScreenObserver::OnExit, 265 base::Unretained(get_screen_observer()), 266 ScreenObserver::ENTERPRISE_ENROLLMENT_COMPLETED)); 267 } 268 } 269 270 void EnrollmentScreen::RegisterForDevicePolicy(const std::string& token) { 271 policy::BrowserPolicyConnectorChromeOS* connector = 272 g_browser_process->platform_part()->browser_policy_connector_chromeos(); 273 if (connector->IsEnterpriseManaged() && 274 connector->GetEnterpriseDomain() != gaia::ExtractDomainName(user_)) { 275 LOG(ERROR) << "Trying to re-enroll to a different domain than " 276 << connector->GetEnterpriseDomain(); 277 UMAFailure(policy::kMetricEnrollmentPrecheckDomainMismatch); 278 actor_->ShowUIError( 279 EnrollmentScreenActor::UI_ERROR_DOMAIN_MISMATCH); 280 return; 281 } 282 283 policy::DeviceCloudPolicyInitializer::AllowedDeviceModes device_modes; 284 device_modes[policy::DEVICE_MODE_ENTERPRISE] = true; 285 device_modes[policy::DEVICE_MODE_RETAIL_KIOSK] = 286 enrollment_mode_ == EnrollmentScreenActor::ENROLLMENT_MODE_MANUAL; 287 connector->ScheduleServiceInitialization(0); 288 289 policy::DeviceCloudPolicyInitializer* dcp_initializer = 290 connector->GetDeviceCloudPolicyInitializer(); 291 CHECK(dcp_initializer); 292 dcp_initializer->StartEnrollment( 293 enterprise_management::PolicyData::ENTERPRISE_MANAGED, 294 connector->device_management_service(), 295 token, is_auto_enrollment(), device_modes, 296 base::Bind(&EnrollmentScreen::ReportEnrollmentStatus, 297 weak_ptr_factory_.GetWeakPtr())); 298 } 299 300 void EnrollmentScreen::SendEnrollmentAuthToken(const std::string& token) { 301 // TODO(achuith, zork): Extract and send domain. 302 if (shark_controller_) 303 shark_controller_->OnAuthenticationDone("", token); 304 } 305 306 void EnrollmentScreen::ShowEnrollmentStatusOnSuccess( 307 const policy::EnrollmentStatus& status) { 308 StartupUtils::MarkOobeCompleted(); 309 if (elapsed_timer_) 310 UMA_ENROLLMENT_TIME("Enterprise.EnrollmentTime.Success", elapsed_timer_); 311 actor_->ShowEnrollmentStatus(status); 312 } 313 314 void EnrollmentScreen::ReportEnrollmentStatus(policy::EnrollmentStatus status) { 315 switch (status.status()) { 316 case policy::EnrollmentStatus::STATUS_SUCCESS: 317 StartupUtils::MarkDeviceRegistered( 318 base::Bind(&EnrollmentScreen::ShowEnrollmentStatusOnSuccess, 319 weak_ptr_factory_.GetWeakPtr(), 320 status)); 321 UMA(is_auto_enrollment() ? policy::kMetricEnrollmentAutoOK 322 : policy::kMetricEnrollmentOK); 323 if (remora_controller_) 324 remora_controller_->SetEnrollmentComplete(true); 325 return; 326 case policy::EnrollmentStatus::STATUS_REGISTRATION_FAILED: 327 case policy::EnrollmentStatus::STATUS_POLICY_FETCH_FAILED: 328 switch (status.client_status()) { 329 case policy::DM_STATUS_SUCCESS: 330 NOTREACHED(); 331 break; 332 case policy::DM_STATUS_REQUEST_INVALID: 333 UMAFailure(policy::kMetricEnrollmentRegisterPolicyPayloadInvalid); 334 break; 335 case policy::DM_STATUS_SERVICE_DEVICE_NOT_FOUND: 336 UMAFailure(policy::kMetricEnrollmentRegisterPolicyDeviceNotFound); 337 break; 338 case policy::DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID: 339 UMAFailure(policy::kMetricEnrollmentRegisterPolicyDMTokenInvalid); 340 break; 341 case policy::DM_STATUS_SERVICE_ACTIVATION_PENDING: 342 UMAFailure(policy::kMetricEnrollmentRegisterPolicyActivationPending); 343 break; 344 case policy::DM_STATUS_SERVICE_DEVICE_ID_CONFLICT: 345 UMAFailure(policy::kMetricEnrollmentRegisterPolicyDeviceIdConflict); 346 break; 347 case policy::DM_STATUS_SERVICE_POLICY_NOT_FOUND: 348 UMAFailure(policy::kMetricEnrollmentRegisterPolicyNotFound); 349 break; 350 case policy::DM_STATUS_REQUEST_FAILED: 351 UMAFailure(policy::kMetricEnrollmentRegisterPolicyRequestFailed); 352 break; 353 case policy::DM_STATUS_TEMPORARY_UNAVAILABLE: 354 UMAFailure(policy::kMetricEnrollmentRegisterPolicyTempUnavailable); 355 break; 356 case policy::DM_STATUS_HTTP_STATUS_ERROR: 357 UMAFailure(policy::kMetricEnrollmentRegisterPolicyHttpError); 358 break; 359 case policy::DM_STATUS_RESPONSE_DECODING_ERROR: 360 UMAFailure(policy::kMetricEnrollmentRegisterPolicyResponseInvalid); 361 break; 362 case policy::DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED: 363 UMAFailure(policy::kMetricEnrollmentNotSupported); 364 break; 365 case policy::DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER: 366 UMAFailure(policy::kMetricEnrollmentRegisterPolicyInvalidSerial); 367 break; 368 case policy::DM_STATUS_SERVICE_MISSING_LICENSES: 369 UMAFailure(policy::kMetricEnrollmentRegisterPolicyMissingLicenses); 370 break; 371 case policy::DM_STATUS_SERVICE_DEPROVISIONED: 372 UMAFailure(policy::kMetricEnrollmentRegisterPolicyDeprovisioned); 373 break; 374 case policy::DM_STATUS_SERVICE_DOMAIN_MISMATCH: 375 UMAFailure(policy::kMetricEnrollmentRegisterPolicyDomainMismatch); 376 break; 377 } 378 break; 379 case policy::EnrollmentStatus::STATUS_REGISTRATION_BAD_MODE: 380 UMAFailure(policy::kMetricEnrollmentInvalidEnrollmentMode); 381 break; 382 case policy::EnrollmentStatus::STATUS_LOCK_TIMEOUT: 383 UMAFailure(policy::kMetricEnrollmentLockboxTimeoutError); 384 break; 385 case policy::EnrollmentStatus::STATUS_LOCK_WRONG_USER: 386 UMAFailure(policy::kMetricEnrollmentLockDomainMismatch); 387 break; 388 case policy::EnrollmentStatus::STATUS_NO_STATE_KEYS: 389 UMAFailure(policy::kMetricEnrollmentNoStateKeys); 390 break; 391 case policy::EnrollmentStatus::STATUS_VALIDATION_FAILED: 392 UMAFailure(policy::kMetricEnrollmentPolicyValidationFailed); 393 break; 394 case policy::EnrollmentStatus::STATUS_STORE_ERROR: 395 UMAFailure(policy::kMetricEnrollmentCloudPolicyStoreError); 396 break; 397 case policy::EnrollmentStatus::STATUS_LOCK_ERROR: 398 UMAFailure(policy::kMetricEnrollmentLockBackendError); 399 break; 400 case policy::EnrollmentStatus::STATUS_ROBOT_AUTH_FETCH_FAILED: 401 UMAFailure(policy::kMetricEnrollmentRobotAuthCodeFetchFailed); 402 break; 403 case policy::EnrollmentStatus::STATUS_ROBOT_REFRESH_FETCH_FAILED: 404 UMAFailure(policy::kMetricEnrollmentRobotRefreshTokenFetchFailed); 405 break; 406 case policy::EnrollmentStatus::STATUS_ROBOT_REFRESH_STORE_FAILED: 407 UMAFailure(policy::kMetricEnrollmentRobotRefreshTokenStoreFailed); 408 break; 409 case policy::EnrollmentStatus::STATUS_STORE_TOKEN_AND_ID_FAILED: 410 // This error should not happen for enterprise enrollment, it only affects 411 // consumer enrollment. 412 UMAFailure(policy::kMetricEnrollmentStoreTokenAndIdFailed); 413 NOTREACHED(); 414 break; 415 } 416 417 if (remora_controller_) 418 remora_controller_->SetEnrollmentComplete(false); 419 enrollment_failed_once_ = true; 420 if (elapsed_timer_) 421 UMA_ENROLLMENT_TIME("Enterprise.EnrollmentTime.Failure", elapsed_timer_); 422 actor_->ShowEnrollmentStatus(status); 423 } 424 425 void EnrollmentScreen::UMA(policy::MetricEnrollment sample) { 426 switch (enrollment_mode_) { 427 case EnrollmentScreenActor::ENROLLMENT_MODE_MANUAL: 428 case EnrollmentScreenActor::ENROLLMENT_MODE_AUTO: 429 UMA_HISTOGRAM_SPARSE_SLOWLY("Enterprise.Enrollment", sample); 430 break; 431 case EnrollmentScreenActor::ENROLLMENT_MODE_FORCED: 432 UMA_HISTOGRAM_SPARSE_SLOWLY("Enterprise.EnrollmentForced", sample); 433 break; 434 case EnrollmentScreenActor::ENROLLMENT_MODE_RECOVERY: 435 UMA_HISTOGRAM_SPARSE_SLOWLY("Enterprise.EnrollmentRecovery", sample); 436 break; 437 case EnrollmentScreenActor::ENROLLMENT_MODE_COUNT: 438 NOTREACHED(); 439 break; 440 } 441 } 442 443 void EnrollmentScreen::UMAFailure(policy::MetricEnrollment sample) { 444 if (is_auto_enrollment()) 445 sample = policy::kMetricEnrollmentAutoFailed; 446 UMA(sample); 447 } 448 449 void EnrollmentScreen::ShowSigninScreen() { 450 actor_->Show(); 451 actor_->ShowSigninScreen(); 452 } 453 454 } // namespace chromeos 455