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