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