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