enrollment_screen.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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_initializer.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#include "policy/proto/device_management_backend.pb.h" 27 28namespace chromeos { 29 30EnrollmentScreen::EnrollmentScreen( 31 ScreenObserver* observer, 32 EnrollmentScreenActor* actor) 33 : WizardScreen(observer), 34 actor_(actor), 35 enrollment_mode_(EnrollmentScreenActor::ENROLLMENT_MODE_MANUAL), 36 enrollment_failed_once_(false), 37 lockbox_init_duration_(0), 38 weak_ptr_factory_(this) { 39 // Init the TPM if it has not been done until now (in debug build we might 40 // have not done that yet). 41 DBusThreadManager::Get()->GetCryptohomeClient()->TpmCanAttemptOwnership( 42 EmptyVoidDBusMethodCallback()); 43} 44 45EnrollmentScreen::~EnrollmentScreen() {} 46 47void EnrollmentScreen::SetParameters( 48 EnrollmentScreenActor::EnrollmentMode enrollment_mode, 49 const std::string& management_domain, 50 const std::string& user) { 51 enrollment_mode_ = enrollment_mode; 52 user_ = user.empty() ? user : gaia::CanonicalizeEmail(user); 53 actor_->SetParameters(this, enrollment_mode_, management_domain); 54} 55 56void EnrollmentScreen::PrepareToShow() { 57 actor_->PrepareToShow(); 58} 59 60void EnrollmentScreen::Show() { 61 if (is_auto_enrollment() && !enrollment_failed_once_) { 62 actor_->Show(); 63 UMA(policy::kMetricEnrollmentAutoStarted); 64 actor_->ShowEnrollmentSpinnerScreen(); 65 actor_->FetchOAuthToken(); 66 } else { 67 UMA(policy::kMetricEnrollmentTriggered); 68 actor_->ResetAuth(base::Bind(&EnrollmentScreen::ShowSigninScreen, 69 weak_ptr_factory_.GetWeakPtr())); 70 } 71} 72 73void EnrollmentScreen::Hide() { 74 actor_->Hide(); 75 weak_ptr_factory_.InvalidateWeakPtrs(); 76} 77 78std::string EnrollmentScreen::GetName() const { 79 return WizardController::kEnrollmentScreenName; 80} 81 82void EnrollmentScreen::OnLoginDone(const std::string& user) { 83 user_ = gaia::CanonicalizeEmail(user); 84 85 if (is_auto_enrollment()) 86 UMA(policy::kMetricEnrollmentAutoRetried); 87 else if (enrollment_failed_once_) 88 UMA(policy::kMetricEnrollmentRetried); 89 else 90 UMA(policy::kMetricEnrollmentStarted); 91 92 actor_->ShowEnrollmentSpinnerScreen(); 93 actor_->FetchOAuthToken(); 94} 95 96void EnrollmentScreen::OnAuthError(const GoogleServiceAuthError& error) { 97 enrollment_failed_once_ = true; 98 actor_->ShowAuthError(error); 99 100 switch (error.state()) { 101 case GoogleServiceAuthError::NONE: 102 case GoogleServiceAuthError::CAPTCHA_REQUIRED: 103 case GoogleServiceAuthError::TWO_FACTOR: 104 case GoogleServiceAuthError::HOSTED_NOT_ALLOWED: 105 case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS: 106 case GoogleServiceAuthError::REQUEST_CANCELED: 107 case GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE: 108 case GoogleServiceAuthError::SERVICE_ERROR: 109 UMAFailure(policy::kMetricEnrollmentLoginFailed); 110 LOG(ERROR) << "Auth error " << error.state(); 111 return; 112 case GoogleServiceAuthError::USER_NOT_SIGNED_UP: 113 case GoogleServiceAuthError::ACCOUNT_DELETED: 114 case GoogleServiceAuthError::ACCOUNT_DISABLED: 115 UMAFailure(policy::kMetricEnrollmentNotSupported); 116 LOG(ERROR) << "Account error " << error.state(); 117 return; 118 case GoogleServiceAuthError::CONNECTION_FAILED: 119 case GoogleServiceAuthError::SERVICE_UNAVAILABLE: 120 UMAFailure(policy::kMetricEnrollmentNetworkFailed); 121 LOG(WARNING) << "Network error " << error.state(); 122 return; 123 case GoogleServiceAuthError::NUM_STATES: 124 break; 125 } 126 127 NOTREACHED(); 128 UMAFailure(policy::kMetricEnrollmentOtherFailed); 129} 130 131void EnrollmentScreen::OnOAuthTokenAvailable(const std::string& token) { 132 RegisterForDevicePolicy(token); 133} 134 135void EnrollmentScreen::OnRetry() { 136 actor_->ResetAuth(base::Bind(&EnrollmentScreen::ShowSigninScreen, 137 weak_ptr_factory_.GetWeakPtr())); 138} 139 140void 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 160void 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 185void EnrollmentScreen::RegisterForDevicePolicy(const std::string& token) { 186 policy::BrowserPolicyConnectorChromeOS* connector = 187 g_browser_process->platform_part()->browser_policy_connector_chromeos(); 188 if (connector->IsEnterpriseManaged() && 189 connector->GetEnterpriseDomain() != gaia::ExtractDomainName(user_)) { 190 LOG(ERROR) << "Trying to re-enroll to a different domain than " 191 << connector->GetEnterpriseDomain(); 192 UMAFailure(policy::kMetricEnrollmentWrongUserError); 193 actor_->ShowUIError( 194 EnrollmentScreenActor::UI_ERROR_DOMAIN_MISMATCH); 195 return; 196 } 197 198 policy::DeviceCloudPolicyInitializer::AllowedDeviceModes device_modes; 199 device_modes[policy::DEVICE_MODE_ENTERPRISE] = true; 200 device_modes[policy::DEVICE_MODE_RETAIL_KIOSK] = 201 enrollment_mode_ == EnrollmentScreenActor::ENROLLMENT_MODE_MANUAL; 202 connector->ScheduleServiceInitialization(0); 203 204 policy::DeviceCloudPolicyInitializer* dcp_initializer = 205 connector->GetDeviceCloudPolicyInitializer(); 206 CHECK(dcp_initializer); 207 dcp_initializer->StartEnrollment( 208 enterprise_management::PolicyData::ENTERPRISE_MANAGED, 209 connector->device_management_service(), 210 token, is_auto_enrollment(), device_modes, 211 base::Bind(&EnrollmentScreen::ReportEnrollmentStatus, 212 weak_ptr_factory_.GetWeakPtr())); 213} 214 215void EnrollmentScreen::ShowEnrollmentStatusOnSuccess( 216 const policy::EnrollmentStatus& status) { 217 actor_->ShowEnrollmentStatus(status); 218 StartupUtils::MarkOobeCompleted(); 219} 220 221void EnrollmentScreen::ReportEnrollmentStatus(policy::EnrollmentStatus status) { 222 if (status.status() == policy::EnrollmentStatus::STATUS_SUCCESS) { 223 StartupUtils::MarkDeviceRegistered( 224 base::Bind(&EnrollmentScreen::ShowEnrollmentStatusOnSuccess, 225 weak_ptr_factory_.GetWeakPtr(), 226 status)); 227 UMA(is_auto_enrollment() ? policy::kMetricEnrollmentAutoOK 228 : policy::kMetricEnrollmentOK); 229 return; 230 } else { 231 enrollment_failed_once_ = true; 232 } 233 actor_->ShowEnrollmentStatus(status); 234 235 switch (status.status()) { 236 case policy::EnrollmentStatus::STATUS_REGISTRATION_FAILED: 237 case policy::EnrollmentStatus::STATUS_POLICY_FETCH_FAILED: 238 switch (status.client_status()) { 239 case policy::DM_STATUS_SUCCESS: 240 case policy::DM_STATUS_REQUEST_INVALID: 241 case policy::DM_STATUS_SERVICE_DEVICE_NOT_FOUND: 242 case policy::DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID: 243 case policy::DM_STATUS_SERVICE_ACTIVATION_PENDING: 244 case policy::DM_STATUS_SERVICE_DEVICE_ID_CONFLICT: 245 case policy::DM_STATUS_SERVICE_POLICY_NOT_FOUND: 246 UMAFailure(policy::kMetricEnrollmentOtherFailed); 247 return; 248 case policy::DM_STATUS_REQUEST_FAILED: 249 case policy::DM_STATUS_TEMPORARY_UNAVAILABLE: 250 case policy::DM_STATUS_HTTP_STATUS_ERROR: 251 case policy::DM_STATUS_RESPONSE_DECODING_ERROR: 252 UMAFailure(policy::kMetricEnrollmentNetworkFailed); 253 return; 254 case policy::DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED: 255 UMAFailure(policy::kMetricEnrollmentNotSupported); 256 return; 257 case policy::DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER: 258 UMAFailure(policy::kMetricEnrollmentInvalidSerialNumber); 259 return; 260 case policy::DM_STATUS_SERVICE_MISSING_LICENSES: 261 UMAFailure(policy::kMetricMissingLicensesError); 262 return; 263 case policy::DM_STATUS_SERVICE_DEPROVISIONED: 264 UMAFailure(policy::kMetricEnrollmentDeprovisioned); 265 return; 266 case policy::DM_STATUS_SERVICE_DOMAIN_MISMATCH: 267 UMAFailure(policy::kMetricEnrollmentDomainMismatch); 268 return; 269 } 270 break; 271 case policy::EnrollmentStatus::STATUS_REGISTRATION_BAD_MODE: 272 UMAFailure(policy::kMetricEnrollmentInvalidEnrollmentMode); 273 return; 274 case policy::EnrollmentStatus::STATUS_LOCK_TIMEOUT: 275 UMAFailure(policy::kMetricLockboxTimeoutError); 276 return; 277 case policy::EnrollmentStatus::STATUS_LOCK_WRONG_USER: 278 UMAFailure(policy::kMetricEnrollmentWrongUserError); 279 return; 280 case policy::EnrollmentStatus::STATUS_NO_STATE_KEYS: 281 case policy::EnrollmentStatus::STATUS_VALIDATION_FAILED: 282 case policy::EnrollmentStatus::STATUS_STORE_ERROR: 283 case policy::EnrollmentStatus::STATUS_LOCK_ERROR: 284 UMAFailure(policy::kMetricEnrollmentOtherFailed); 285 return; 286 case policy::EnrollmentStatus::STATUS_ROBOT_AUTH_FETCH_FAILED: 287 UMAFailure(policy::kMetricEnrollmentRobotAuthCodeFetchFailed); 288 return; 289 case policy::EnrollmentStatus::STATUS_ROBOT_REFRESH_FETCH_FAILED: 290 UMAFailure(policy::kMetricEnrollmentRobotRefreshTokenFetchFailed); 291 return; 292 case policy::EnrollmentStatus::STATUS_ROBOT_REFRESH_STORE_FAILED: 293 UMAFailure(policy::kMetricEnrollmentRobotRefreshTokenStoreFailed); 294 return; 295 case policy::EnrollmentStatus::STATUS_STORE_TOKEN_AND_ID_FAILED: 296 // This error should not happen for enterprise enrollment. 297 UMAFailure(policy::kMetricEnrollmentStoreTokenAndIdFailed); 298 NOTREACHED(); 299 return; 300 case policy::EnrollmentStatus::STATUS_SUCCESS: 301 NOTREACHED(); 302 return; 303 } 304 305 NOTREACHED(); 306 UMAFailure(policy::kMetricEnrollmentOtherFailed); 307} 308 309void EnrollmentScreen::UMA(policy::MetricEnrollment sample) { 310 if (enrollment_mode_ == EnrollmentScreenActor::ENROLLMENT_MODE_RECOVERY) { 311 UMA_HISTOGRAM_ENUMERATION(policy::kMetricEnrollmentRecovery, sample, 312 policy::kMetricEnrollmentSize); 313 } else { 314 UMA_HISTOGRAM_ENUMERATION(policy::kMetricEnrollment, sample, 315 policy::kMetricEnrollmentSize); 316 } 317} 318 319void EnrollmentScreen::UMAFailure(policy::MetricEnrollment sample) { 320 if (is_auto_enrollment()) 321 sample = policy::kMetricEnrollmentAutoFailed; 322 UMA(sample); 323} 324 325void EnrollmentScreen::ShowSigninScreen() { 326 actor_->Show(); 327 actor_->ShowSigninScreen(); 328} 329 330} // namespace chromeos 331