enrollment_screen.cc revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
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_method_call_status.h" 23#include "chromeos/dbus/dbus_thread_manager.h" 24#include "chromeos/dbus/session_manager_client.h" 25#include "google_apis/gaia/gaia_auth_util.h" 26#include "google_apis/gaia/google_service_auth_error.h" 27 28namespace chromeos { 29 30namespace { 31 32void UMA(int sample) { 33 UMA_HISTOGRAM_ENUMERATION(policy::kMetricEnrollment, 34 sample, 35 policy::kMetricEnrollmentSize); 36} 37 38} // namespace 39 40EnrollmentScreen::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 56EnrollmentScreen::~EnrollmentScreen() {} 57 58void 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 67void EnrollmentScreen::PrepareToShow() { 68 actor_->PrepareToShow(); 69} 70 71void 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 83void EnrollmentScreen::Hide() { 84 actor_->Hide(); 85 weak_ptr_factory_.InvalidateWeakPtrs(); 86} 87 88std::string EnrollmentScreen::GetName() const { 89 return WizardController::kEnrollmentScreenName; 90} 91 92void 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 102void 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 138void EnrollmentScreen::OnOAuthTokenAvailable( 139 const std::string& token) { 140 RegisterForDevicePolicy(token); 141} 142 143void EnrollmentScreen::OnRetry() { 144 actor_->ResetAuth(base::Bind(&EnrollmentScreen::ShowSigninScreen, 145 weak_ptr_factory_.GetWeakPtr())); 146} 147 148void EnrollmentScreen::OnCancel() { 149 if (!can_exit_enrollment_) { 150 NOTREACHED() << "Cancellation should not be permitted"; 151 return; 152 } 153 154 if (is_auto_enrollment_) 155 policy::AutoEnrollmentClient::CancelAutoEnrollment(); 156 UMA(is_auto_enrollment_ ? policy::kMetricEnrollmentAutoCancelled 157 : policy::kMetricEnrollmentCancelled); 158 actor_->ResetAuth( 159 base::Bind(&ScreenObserver::OnExit, 160 base::Unretained(get_screen_observer()), 161 ScreenObserver::ENTERPRISE_ENROLLMENT_COMPLETED)); 162} 163 164void EnrollmentScreen::OnConfirmationClosed() { 165 // If the machine has been put in KIOSK mode we have to restart the session 166 // here to go in the proper KIOSK mode login screen. 167 if (g_browser_process->browser_policy_connector()->GetDeviceMode() == 168 policy::DEVICE_MODE_RETAIL_KIOSK) { 169 DBusThreadManager::Get()->GetSessionManagerClient()->StopSession(); 170 return; 171 } 172 173 if (is_auto_enrollment_ && 174 !enrollment_failed_once_ && 175 !user_.empty() && 176 LoginUtils::IsWhitelisted(user_)) { 177 actor_->ShowLoginSpinnerScreen(); 178 get_screen_observer()->OnExit( 179 ScreenObserver::ENTERPRISE_AUTO_MAGIC_ENROLLMENT_COMPLETED); 180 } else { 181 actor_->ResetAuth( 182 base::Bind(&ScreenObserver::OnExit, 183 base::Unretained(get_screen_observer()), 184 ScreenObserver::ENTERPRISE_ENROLLMENT_COMPLETED)); 185 } 186} 187 188void EnrollmentScreen::RegisterForDevicePolicy( 189 const std::string& token) { 190 policy::BrowserPolicyConnector* connector = 191 g_browser_process->browser_policy_connector(); 192 if (connector->IsEnterpriseManaged() && 193 connector->GetEnterpriseDomain() != gaia::ExtractDomainName(user_)) { 194 LOG(ERROR) << "Trying to re-enroll to a different domain than " 195 << connector->GetEnterpriseDomain(); 196 UMAFailure(policy::kMetricEnrollmentWrongUserError); 197 actor_->ShowUIError( 198 EnrollmentScreenActor::UI_ERROR_DOMAIN_MISMATCH); 199 return; 200 } 201 202 policy::DeviceCloudPolicyManagerChromeOS::AllowedDeviceModes modes; 203 modes[policy::DEVICE_MODE_ENTERPRISE] = true; 204 modes[policy::DEVICE_MODE_RETAIL_KIOSK] = !is_auto_enrollment_; 205 connector->ScheduleServiceInitialization(0); 206 connector->GetDeviceCloudPolicyManager()->StartEnrollment( 207 token, is_auto_enrollment_, modes, 208 base::Bind(&EnrollmentScreen::ReportEnrollmentStatus, 209 weak_ptr_factory_.GetWeakPtr())); 210} 211 212void EnrollmentScreen::ReportEnrollmentStatus( 213 policy::EnrollmentStatus status) { 214 bool success = status.status() == policy::EnrollmentStatus::STATUS_SUCCESS; 215 enrollment_failed_once_ |= !success; 216 actor_->ShowEnrollmentStatus(status); 217 218 switch (status.status()) { 219 case policy::EnrollmentStatus::STATUS_SUCCESS: 220 StartupUtils::MarkDeviceRegistered(); 221 UMA(is_auto_enrollment_ ? policy::kMetricEnrollmentAutoOK 222 : policy::kMetricEnrollmentOK); 223 return; 224 case policy::EnrollmentStatus::STATUS_REGISTRATION_FAILED: 225 case policy::EnrollmentStatus::STATUS_POLICY_FETCH_FAILED: 226 switch (status.client_status()) { 227 case policy::DM_STATUS_SUCCESS: 228 case policy::DM_STATUS_REQUEST_INVALID: 229 case policy::DM_STATUS_SERVICE_DEVICE_NOT_FOUND: 230 case policy::DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID: 231 case policy::DM_STATUS_SERVICE_ACTIVATION_PENDING: 232 case policy::DM_STATUS_SERVICE_DEVICE_ID_CONFLICT: 233 case policy::DM_STATUS_SERVICE_POLICY_NOT_FOUND: 234 UMAFailure(policy::kMetricEnrollmentOtherFailed); 235 return; 236 case policy::DM_STATUS_REQUEST_FAILED: 237 case policy::DM_STATUS_TEMPORARY_UNAVAILABLE: 238 case policy::DM_STATUS_HTTP_STATUS_ERROR: 239 case policy::DM_STATUS_RESPONSE_DECODING_ERROR: 240 UMAFailure(policy::kMetricEnrollmentNetworkFailed); 241 return; 242 case policy::DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED: 243 UMAFailure(policy::kMetricEnrollmentNotSupported); 244 return; 245 case policy::DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER: 246 UMAFailure(policy::kMetricEnrollmentInvalidSerialNumber); 247 return; 248 case policy::DM_STATUS_SERVICE_MISSING_LICENSES: 249 UMAFailure(policy::kMetricMissingLicensesError); 250 return; 251 } 252 break; 253 case policy::EnrollmentStatus::STATUS_REGISTRATION_BAD_MODE: 254 UMAFailure(policy::kMetricEnrollmentInvalidEnrollmentMode); 255 return; 256 case policy::EnrollmentStatus::STATUS_LOCK_TIMEOUT: 257 UMAFailure(policy::kMetricLockboxTimeoutError); 258 return; 259 case policy::EnrollmentStatus::STATUS_LOCK_WRONG_USER: 260 UMAFailure(policy::kMetricEnrollmentWrongUserError); 261 return; 262 case policy::EnrollmentStatus::STATUS_VALIDATION_FAILED: 263 case policy::EnrollmentStatus::STATUS_STORE_ERROR: 264 case policy::EnrollmentStatus::STATUS_LOCK_ERROR: 265 UMAFailure(policy::kMetricEnrollmentOtherFailed); 266 return; 267 } 268 269 NOTREACHED(); 270 UMAFailure(policy::kMetricEnrollmentOtherFailed); 271} 272 273void EnrollmentScreen::UMAFailure(int sample) { 274 if (is_auto_enrollment_) 275 sample = policy::kMetricEnrollmentAutoFailed; 276 UMA(sample); 277} 278 279void EnrollmentScreen::ShowSigninScreen() { 280 actor_->Show(); 281 actor_->ShowSigninScreen(); 282} 283 284} // namespace chromeos 285