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.
5 #include "chrome/browser/chromeos/login/enrollment/enrollment_screen.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/browser_process_platform_part.h"
14 #include "chrome/browser/chromeos/login/login_utils.h"
15 #include "chrome/browser/chromeos/login/screen_manager.h"
16 #include "chrome/browser/chromeos/login/screens/screen_observer.h"
17 #include "chrome/browser/chromeos/login/startup_utils.h"
18 #include "chrome/browser/chromeos/login/wizard_controller.h"
19 #include "chrome/browser/chromeos/policy/auto_enrollment_client.h"
20 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
21 #include "chrome/browser/chromeos/policy/device_cloud_policy_initializer.h"
22 #include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h"
23 #include "chromeos/dbus/cryptohome_client.h"
24 #include "chromeos/dbus/dbus_method_call_status.h"
25 #include "chromeos/dbus/dbus_thread_manager.h"
26 #include "chromeos/dbus/session_manager_client.h"
27 #include "google_apis/gaia/gaia_auth_util.h"
28 #include "google_apis/gaia/google_service_auth_error.h"
29 #include "policy/proto/device_management_backend.pb.h"
34 EnrollmentScreen
* EnrollmentScreen::Get(ScreenManager
* manager
) {
35 return static_cast<EnrollmentScreen
*>(
36 manager
->GetScreen(WizardController::kEnrollmentScreenName
));
39 EnrollmentScreen::EnrollmentScreen(
40 ScreenObserver
* observer
,
41 EnrollmentScreenActor
* actor
)
42 : WizardScreen(observer
),
44 enrollment_mode_(EnrollmentScreenActor::ENROLLMENT_MODE_MANUAL
),
45 enrollment_failed_once_(false),
46 remora_token_sent_(false),
47 lockbox_init_duration_(0),
48 weak_ptr_factory_(this) {
49 // Init the TPM if it has not been done until now (in debug build we might
50 // have not done that yet).
51 DBusThreadManager::Get()->GetCryptohomeClient()->TpmCanAttemptOwnership(
52 EmptyVoidDBusMethodCallback());
55 EnrollmentScreen::~EnrollmentScreen() {}
57 void EnrollmentScreen::SetParameters(
58 EnrollmentScreenActor::EnrollmentMode enrollment_mode
,
59 const std::string
& management_domain
,
60 const std::string
& user
,
61 const std::string
& auth_token
) {
62 enrollment_mode_
= enrollment_mode
;
63 user_
= user
.empty() ? user
: gaia::CanonicalizeEmail(user
);
64 auth_token_
= auth_token
;
65 actor_
->SetParameters(this, enrollment_mode_
, management_domain
);
68 void EnrollmentScreen::PrepareToShow() {
69 actor_
->PrepareToShow();
72 void EnrollmentScreen::Show() {
73 if (is_auto_enrollment() && !enrollment_failed_once_
) {
75 UMA(policy::kMetricEnrollmentAutoStarted
);
76 actor_
->ShowEnrollmentSpinnerScreen();
77 actor_
->FetchOAuthToken();
78 } else if (auth_token_
.empty()) {
79 UMA(policy::kMetricEnrollmentTriggered
);
80 actor_
->ResetAuth(base::Bind(&EnrollmentScreen::ShowSigninScreen
,
81 weak_ptr_factory_
.GetWeakPtr()));
84 actor_
->ShowEnrollmentSpinnerScreen();
85 OnOAuthTokenAvailable(auth_token_
);
89 void EnrollmentScreen::Hide() {
91 weak_ptr_factory_
.InvalidateWeakPtrs();
94 std::string
EnrollmentScreen::GetName() const {
95 return WizardController::kEnrollmentScreenName
;
98 void EnrollmentScreen::OnLoginDone(const std::string
& user
) {
99 user_
= gaia::CanonicalizeEmail(user
);
101 if (is_auto_enrollment())
102 UMA(policy::kMetricEnrollmentAutoRetried
);
103 else if (enrollment_failed_once_
)
104 UMA(policy::kMetricEnrollmentRetried
);
106 UMA(policy::kMetricEnrollmentStarted
);
108 actor_
->ShowEnrollmentSpinnerScreen();
109 actor_
->FetchOAuthToken();
112 void EnrollmentScreen::OnAuthError(const GoogleServiceAuthError
& error
) {
113 enrollment_failed_once_
= true;
114 actor_
->ShowAuthError(error
);
116 switch (error
.state()) {
117 case GoogleServiceAuthError::NONE
:
118 case GoogleServiceAuthError::CAPTCHA_REQUIRED
:
119 case GoogleServiceAuthError::TWO_FACTOR
:
120 case GoogleServiceAuthError::HOSTED_NOT_ALLOWED
:
121 case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS
:
122 case GoogleServiceAuthError::REQUEST_CANCELED
:
123 case GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE
:
124 case GoogleServiceAuthError::SERVICE_ERROR
:
125 UMAFailure(policy::kMetricEnrollmentLoginFailed
);
126 LOG(ERROR
) << "Auth error " << error
.state();
128 case GoogleServiceAuthError::USER_NOT_SIGNED_UP
:
129 case GoogleServiceAuthError::ACCOUNT_DELETED
:
130 case GoogleServiceAuthError::ACCOUNT_DISABLED
:
131 UMAFailure(policy::kMetricEnrollmentNotSupported
);
132 LOG(ERROR
) << "Account error " << error
.state();
134 case GoogleServiceAuthError::CONNECTION_FAILED
:
135 case GoogleServiceAuthError::SERVICE_UNAVAILABLE
:
136 UMAFailure(policy::kMetricEnrollmentNetworkFailed
);
137 LOG(WARNING
) << "Network error " << error
.state();
139 case GoogleServiceAuthError::NUM_STATES
:
144 UMAFailure(policy::kMetricEnrollmentOtherFailed
);
147 void EnrollmentScreen::OnOAuthTokenAvailable(const std::string
& token
) {
148 VLOG(1) << "OnOAuthTokenAvailable " << token
;
149 const bool is_shark
=
150 g_browser_process
->platform_part()->browser_policy_connector_chromeos()->
151 GetDeviceCloudPolicyManager()->IsSharkRequisition();
153 if (is_shark
&& !remora_token_sent_
) {
154 // Fetch a second token for shark devices.
155 remora_token_sent_
= true;
156 SendEnrollmentAuthToken(token
);
157 actor_
->FetchOAuthToken();
159 RegisterForDevicePolicy(token
);
163 void EnrollmentScreen::OnRetry() {
164 actor_
->ResetAuth(base::Bind(&EnrollmentScreen::ShowSigninScreen
,
165 weak_ptr_factory_
.GetWeakPtr()));
168 void EnrollmentScreen::OnCancel() {
169 if (enrollment_mode_
== EnrollmentScreenActor::ENROLLMENT_MODE_FORCED
||
170 enrollment_mode_
== EnrollmentScreenActor::ENROLLMENT_MODE_RECOVERY
) {
172 base::Bind(&ScreenObserver::OnExit
,
173 base::Unretained(get_screen_observer()),
174 ScreenObserver::ENTERPRISE_ENROLLMENT_BACK
));
178 if (is_auto_enrollment())
179 policy::AutoEnrollmentClient::CancelAutoEnrollment();
180 UMA(is_auto_enrollment() ? policy::kMetricEnrollmentAutoCancelled
181 : policy::kMetricEnrollmentCancelled
);
183 base::Bind(&ScreenObserver::OnExit
,
184 base::Unretained(get_screen_observer()),
185 ScreenObserver::ENTERPRISE_ENROLLMENT_COMPLETED
));
188 void EnrollmentScreen::OnConfirmationClosed() {
189 // If the machine has been put in KIOSK mode we have to restart the session
190 // here to go in the proper KIOSK mode login screen.
191 policy::BrowserPolicyConnectorChromeOS
* connector
=
192 g_browser_process
->platform_part()->browser_policy_connector_chromeos();
193 if (connector
->GetDeviceMode() == policy::DEVICE_MODE_RETAIL_KIOSK
) {
194 DBusThreadManager::Get()->GetSessionManagerClient()->StopSession();
198 if (is_auto_enrollment() &&
199 !enrollment_failed_once_
&&
201 LoginUtils::IsWhitelisted(user_
, NULL
)) {
202 actor_
->ShowLoginSpinnerScreen();
203 get_screen_observer()->OnExit(
204 ScreenObserver::ENTERPRISE_AUTO_MAGIC_ENROLLMENT_COMPLETED
);
207 base::Bind(&ScreenObserver::OnExit
,
208 base::Unretained(get_screen_observer()),
209 ScreenObserver::ENTERPRISE_ENROLLMENT_COMPLETED
));
213 void EnrollmentScreen::RegisterForDevicePolicy(const std::string
& token
) {
214 policy::BrowserPolicyConnectorChromeOS
* connector
=
215 g_browser_process
->platform_part()->browser_policy_connector_chromeos();
216 if (connector
->IsEnterpriseManaged() &&
217 connector
->GetEnterpriseDomain() != gaia::ExtractDomainName(user_
)) {
218 LOG(ERROR
) << "Trying to re-enroll to a different domain than "
219 << connector
->GetEnterpriseDomain();
220 UMAFailure(policy::kMetricEnrollmentWrongUserError
);
222 EnrollmentScreenActor::UI_ERROR_DOMAIN_MISMATCH
);
226 policy::DeviceCloudPolicyInitializer::AllowedDeviceModes device_modes
;
227 device_modes
[policy::DEVICE_MODE_ENTERPRISE
] = true;
228 device_modes
[policy::DEVICE_MODE_RETAIL_KIOSK
] =
229 enrollment_mode_
== EnrollmentScreenActor::ENROLLMENT_MODE_MANUAL
;
230 connector
->ScheduleServiceInitialization(0);
232 policy::DeviceCloudPolicyInitializer
* dcp_initializer
=
233 connector
->GetDeviceCloudPolicyInitializer();
234 CHECK(dcp_initializer
);
235 dcp_initializer
->StartEnrollment(
236 enterprise_management::PolicyData::ENTERPRISE_MANAGED
,
237 connector
->device_management_service(),
238 token
, is_auto_enrollment(), device_modes
,
239 base::Bind(&EnrollmentScreen::ReportEnrollmentStatus
,
240 weak_ptr_factory_
.GetWeakPtr()));
243 void EnrollmentScreen::SendEnrollmentAuthToken(const std::string
& token
) {
244 // TODO(achuith, zork): Send token via Bluetooth to remote device.
247 void EnrollmentScreen::ShowEnrollmentStatusOnSuccess(
248 const policy::EnrollmentStatus
& status
) {
249 actor_
->ShowEnrollmentStatus(status
);
250 StartupUtils::MarkOobeCompleted();
253 void EnrollmentScreen::ReportEnrollmentStatus(policy::EnrollmentStatus status
) {
254 if (status
.status() == policy::EnrollmentStatus::STATUS_SUCCESS
) {
255 StartupUtils::MarkDeviceRegistered(
256 base::Bind(&EnrollmentScreen::ShowEnrollmentStatusOnSuccess
,
257 weak_ptr_factory_
.GetWeakPtr(),
259 UMA(is_auto_enrollment() ? policy::kMetricEnrollmentAutoOK
260 : policy::kMetricEnrollmentOK
);
263 enrollment_failed_once_
= true;
265 actor_
->ShowEnrollmentStatus(status
);
267 switch (status
.status()) {
268 case policy::EnrollmentStatus::STATUS_REGISTRATION_FAILED
:
269 case policy::EnrollmentStatus::STATUS_POLICY_FETCH_FAILED
:
270 switch (status
.client_status()) {
271 case policy::DM_STATUS_SUCCESS
:
272 case policy::DM_STATUS_REQUEST_INVALID
:
273 case policy::DM_STATUS_SERVICE_DEVICE_NOT_FOUND
:
274 case policy::DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID
:
275 case policy::DM_STATUS_SERVICE_ACTIVATION_PENDING
:
276 case policy::DM_STATUS_SERVICE_DEVICE_ID_CONFLICT
:
277 case policy::DM_STATUS_SERVICE_POLICY_NOT_FOUND
:
278 UMAFailure(policy::kMetricEnrollmentOtherFailed
);
280 case policy::DM_STATUS_REQUEST_FAILED
:
281 case policy::DM_STATUS_TEMPORARY_UNAVAILABLE
:
282 case policy::DM_STATUS_HTTP_STATUS_ERROR
:
283 case policy::DM_STATUS_RESPONSE_DECODING_ERROR
:
284 UMAFailure(policy::kMetricEnrollmentNetworkFailed
);
286 case policy::DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED
:
287 UMAFailure(policy::kMetricEnrollmentNotSupported
);
289 case policy::DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER
:
290 UMAFailure(policy::kMetricEnrollmentInvalidSerialNumber
);
292 case policy::DM_STATUS_SERVICE_MISSING_LICENSES
:
293 UMAFailure(policy::kMetricMissingLicensesError
);
295 case policy::DM_STATUS_SERVICE_DEPROVISIONED
:
296 UMAFailure(policy::kMetricEnrollmentDeprovisioned
);
298 case policy::DM_STATUS_SERVICE_DOMAIN_MISMATCH
:
299 UMAFailure(policy::kMetricEnrollmentDomainMismatch
);
303 case policy::EnrollmentStatus::STATUS_REGISTRATION_BAD_MODE
:
304 UMAFailure(policy::kMetricEnrollmentInvalidEnrollmentMode
);
306 case policy::EnrollmentStatus::STATUS_LOCK_TIMEOUT
:
307 UMAFailure(policy::kMetricLockboxTimeoutError
);
309 case policy::EnrollmentStatus::STATUS_LOCK_WRONG_USER
:
310 UMAFailure(policy::kMetricEnrollmentWrongUserError
);
312 case policy::EnrollmentStatus::STATUS_NO_STATE_KEYS
:
313 UMAFailure(policy::kMetricEnrollmentNoStateKeys
);
315 case policy::EnrollmentStatus::STATUS_VALIDATION_FAILED
:
316 UMAFailure(policy::kMetricEnrollmentPolicyValidationFailed
);
318 case policy::EnrollmentStatus::STATUS_STORE_ERROR
:
319 UMAFailure(policy::kMetricEnrollmentCloudPolicyStoreError
);
321 case policy::EnrollmentStatus::STATUS_LOCK_ERROR
:
322 UMAFailure(policy::kMetricEnrollmentLockBackendError
);
324 case policy::EnrollmentStatus::STATUS_ROBOT_AUTH_FETCH_FAILED
:
325 UMAFailure(policy::kMetricEnrollmentRobotAuthCodeFetchFailed
);
327 case policy::EnrollmentStatus::STATUS_ROBOT_REFRESH_FETCH_FAILED
:
328 UMAFailure(policy::kMetricEnrollmentRobotRefreshTokenFetchFailed
);
330 case policy::EnrollmentStatus::STATUS_ROBOT_REFRESH_STORE_FAILED
:
331 UMAFailure(policy::kMetricEnrollmentRobotRefreshTokenStoreFailed
);
333 case policy::EnrollmentStatus::STATUS_STORE_TOKEN_AND_ID_FAILED
:
334 // This error should not happen for enterprise enrollment.
335 UMAFailure(policy::kMetricEnrollmentStoreTokenAndIdFailed
);
338 case policy::EnrollmentStatus::STATUS_SUCCESS
:
344 UMAFailure(policy::kMetricEnrollmentOtherFailed
);
347 void EnrollmentScreen::UMA(policy::MetricEnrollment sample
) {
348 if (enrollment_mode_
== EnrollmentScreenActor::ENROLLMENT_MODE_RECOVERY
) {
349 UMA_HISTOGRAM_ENUMERATION(policy::kMetricEnrollmentRecovery
, sample
,
350 policy::kMetricEnrollmentSize
);
352 UMA_HISTOGRAM_ENUMERATION(policy::kMetricEnrollment
, sample
,
353 policy::kMetricEnrollmentSize
);
357 void EnrollmentScreen::UMAFailure(policy::MetricEnrollment sample
) {
358 if (is_auto_enrollment())
359 sample
= policy::kMetricEnrollmentAutoFailed
;
363 void EnrollmentScreen::ShowSigninScreen() {
365 actor_
->ShowSigninScreen();
368 } // namespace chromeos