• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "base/metrics/sparse_histogram.h"
13 #include "base/timer/elapsed_timer.h"
14 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/browser_process_platform_part.h"
16 #include "chrome/browser/chromeos/login/login_utils.h"
17 #include "chrome/browser/chromeos/login/screen_manager.h"
18 #include "chrome/browser/chromeos/login/screens/screen_observer.h"
19 #include "chrome/browser/chromeos/login/startup_utils.h"
20 #include "chrome/browser/chromeos/login/wizard_controller.h"
21 #include "chrome/browser/chromeos/policy/auto_enrollment_client.h"
22 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
23 #include "chrome/browser/chromeos/policy/device_cloud_policy_initializer.h"
24 #include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h"
25 #include "chromeos/dbus/cryptohome_client.h"
26 #include "chromeos/dbus/dbus_method_call_status.h"
27 #include "chromeos/dbus/dbus_thread_manager.h"
28 #include "chromeos/dbus/session_manager_client.h"
29 #include "components/pairing/controller_pairing_controller.h"
30 #include "google_apis/gaia/gaia_auth_util.h"
31 #include "google_apis/gaia/google_service_auth_error.h"
32 #include "policy/proto/device_management_backend.pb.h"
33 
34 using namespace pairing_chromeos;
35 
36 // Do not change the UMA histogram parameters without renaming the histograms!
37 #define UMA_ENROLLMENT_TIME(histogram_name, elapsed_timer) \
38   do {                                                     \
39     UMA_HISTOGRAM_CUSTOM_TIMES(                            \
40       (histogram_name),                                    \
41       (elapsed_timer)->Elapsed(),                          \
42       base::TimeDelta::FromMilliseconds(100) /* min */,    \
43       base::TimeDelta::FromMinutes(15) /* max */,          \
44       100 /* bucket_count */);                             \
45   } while (0)
46 
47 namespace chromeos {
48 
49 // static
Get(ScreenManager * manager)50 EnrollmentScreen* EnrollmentScreen::Get(ScreenManager* manager) {
51   return static_cast<EnrollmentScreen*>(
52       manager->GetScreen(WizardController::kEnrollmentScreenName));
53 }
54 
EnrollmentScreen(ScreenObserver * observer,EnrollmentScreenActor * actor)55 EnrollmentScreen::EnrollmentScreen(
56     ScreenObserver* observer,
57     EnrollmentScreenActor* actor)
58     : WizardScreen(observer),
59       shark_controller_(NULL),
60       remora_controller_(NULL),
61       actor_(actor),
62       enrollment_mode_(EnrollmentScreenActor::ENROLLMENT_MODE_MANUAL),
63       enrollment_failed_once_(false),
64       remora_token_sent_(false),
65       lockbox_init_duration_(0),
66       weak_ptr_factory_(this) {
67   // Init the TPM if it has not been done until now (in debug build we might
68   // have not done that yet).
69   DBusThreadManager::Get()->GetCryptohomeClient()->TpmCanAttemptOwnership(
70       EmptyVoidDBusMethodCallback());
71 }
72 
~EnrollmentScreen()73 EnrollmentScreen::~EnrollmentScreen() {
74   if (remora_controller_)
75     remora_controller_->RemoveObserver(this);
76 }
77 
SetParameters(EnrollmentScreenActor::EnrollmentMode enrollment_mode,const std::string & management_domain,const std::string & user,const std::string & auth_token,pairing_chromeos::ControllerPairingController * shark_controller,pairing_chromeos::HostPairingController * remora_controller)78 void EnrollmentScreen::SetParameters(
79     EnrollmentScreenActor::EnrollmentMode enrollment_mode,
80     const std::string& management_domain,
81     const std::string& user,
82     const std::string& auth_token,
83     pairing_chromeos::ControllerPairingController* shark_controller,
84     pairing_chromeos::HostPairingController* remora_controller) {
85   enrollment_mode_ = enrollment_mode;
86   user_ = user.empty() ? user : gaia::CanonicalizeEmail(user);
87   auth_token_ = auth_token;
88   shark_controller_ = shark_controller;
89   if (remora_controller_)
90     remora_controller_->RemoveObserver(this);
91   remora_controller_ = remora_controller;
92   if (remora_controller_)
93     remora_controller_->AddObserver(this);
94   actor_->SetParameters(this, enrollment_mode_, management_domain);
95 }
96 
PrepareToShow()97 void EnrollmentScreen::PrepareToShow() {
98   actor_->PrepareToShow();
99 }
100 
Show()101 void EnrollmentScreen::Show() {
102   if (is_auto_enrollment() && !enrollment_failed_once_) {
103     actor_->Show();
104     UMA(policy::kMetricEnrollmentAutoStarted);
105     actor_->ShowEnrollmentSpinnerScreen();
106     actor_->FetchOAuthToken();
107   } else if (auth_token_.empty()) {
108     UMA(policy::kMetricEnrollmentTriggered);
109     actor_->ResetAuth(base::Bind(&EnrollmentScreen::ShowSigninScreen,
110                                  weak_ptr_factory_.GetWeakPtr()));
111   } else {
112     actor_->Show();
113     actor_->ShowEnrollmentSpinnerScreen();
114     OnOAuthTokenAvailable(auth_token_);
115   }
116 }
117 
Hide()118 void EnrollmentScreen::Hide() {
119   actor_->Hide();
120   weak_ptr_factory_.InvalidateWeakPtrs();
121 }
122 
GetName() const123 std::string EnrollmentScreen::GetName() const {
124   return WizardController::kEnrollmentScreenName;
125 }
126 
PairingStageChanged(Stage new_stage)127 void EnrollmentScreen::PairingStageChanged(Stage new_stage) {
128   DCHECK(remora_controller_);
129   if (new_stage == HostPairingController::STAGE_FINISHED) {
130     remora_controller_->RemoveObserver(this);
131     remora_controller_ = NULL;
132     // TODO(zork): Check that this is the best exit status. crbug.com/412798
133     get_screen_observer()->OnExit(
134         WizardController::ENTERPRISE_AUTO_MAGIC_ENROLLMENT_COMPLETED);
135   }
136 }
137 
ConfigureHost(bool accepted_eula,const std::string & lang,const std::string & timezone,bool send_reports,const std::string & keyboard_layout)138 void EnrollmentScreen::ConfigureHost(bool accepted_eula,
139                                      const std::string& lang,
140                                      const std::string& timezone,
141                                      bool send_reports,
142                                      const std::string& keyboard_layout) {
143 }
144 
EnrollHost(const std::string & auth_token)145 void EnrollmentScreen::EnrollHost(const std::string& auth_token) {
146 }
147 
OnLoginDone(const std::string & user)148 void EnrollmentScreen::OnLoginDone(const std::string& user) {
149   elapsed_timer_.reset(new base::ElapsedTimer());
150   user_ = gaia::CanonicalizeEmail(user);
151 
152   if (is_auto_enrollment())
153     UMA(policy::kMetricEnrollmentAutoRestarted);
154   else if (enrollment_failed_once_)
155     UMA(policy::kMetricEnrollmentRestarted);
156   else
157     UMA(policy::kMetricEnrollmentStarted);
158 
159   actor_->ShowEnrollmentSpinnerScreen();
160   actor_->FetchOAuthToken();
161 }
162 
OnAuthError(const GoogleServiceAuthError & error)163 void EnrollmentScreen::OnAuthError(const GoogleServiceAuthError& error) {
164   switch (error.state()) {
165     case GoogleServiceAuthError::NONE:
166     case GoogleServiceAuthError::CAPTCHA_REQUIRED:
167     case GoogleServiceAuthError::TWO_FACTOR:
168     case GoogleServiceAuthError::HOSTED_NOT_ALLOWED:
169     case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS:
170     case GoogleServiceAuthError::REQUEST_CANCELED:
171     case GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE:
172     case GoogleServiceAuthError::SERVICE_ERROR:
173       UMAFailure(policy::kMetricEnrollmentLoginFailed);
174       LOG(ERROR) << "Auth error " << error.state();
175       break;
176     case GoogleServiceAuthError::USER_NOT_SIGNED_UP:
177       UMAFailure(policy::kMetricEnrollmentAccountNotSignedUp);
178       LOG(ERROR) << "Account not signed up " << error.state();
179       break;
180     case GoogleServiceAuthError::ACCOUNT_DELETED:
181       UMAFailure(policy::kMetricEnrollmentAccountDeleted);
182       LOG(ERROR) << "Account deleted " << error.state();
183       break;
184     case GoogleServiceAuthError::ACCOUNT_DISABLED:
185       UMAFailure(policy::kMetricEnrollmentAccountDisabled);
186       LOG(ERROR) << "Account disabled " << error.state();
187       break;
188     case GoogleServiceAuthError::CONNECTION_FAILED:
189     case GoogleServiceAuthError::SERVICE_UNAVAILABLE:
190       UMAFailure(policy::kMetricEnrollmentNetworkFailed);
191       LOG(WARNING) << "Network error " << error.state();
192       break;
193     case GoogleServiceAuthError::NUM_STATES:
194       NOTREACHED();
195       break;
196   }
197 
198   enrollment_failed_once_ = true;
199   actor_->ShowAuthError(error);
200 }
201 
OnOAuthTokenAvailable(const std::string & token)202 void EnrollmentScreen::OnOAuthTokenAvailable(const std::string& token) {
203   VLOG(1) << "OnOAuthTokenAvailable " << token;
204   const bool is_shark =
205       g_browser_process->platform_part()->browser_policy_connector_chromeos()->
206           GetDeviceCloudPolicyManager()->IsSharkRequisition();
207 
208   if (is_shark && !remora_token_sent_) {
209     // Fetch a second token for shark devices.
210     remora_token_sent_ = true;
211     SendEnrollmentAuthToken(token);
212     actor_->FetchOAuthToken();
213   } else {
214     RegisterForDevicePolicy(token);
215   }
216 }
217 
OnRetry()218 void EnrollmentScreen::OnRetry() {
219   actor_->ResetAuth(base::Bind(&EnrollmentScreen::ShowSigninScreen,
220                                weak_ptr_factory_.GetWeakPtr()));
221 }
222 
OnCancel()223 void EnrollmentScreen::OnCancel() {
224   UMA(is_auto_enrollment() ? policy::kMetricEnrollmentAutoCancelled
225                            : policy::kMetricEnrollmentCancelled);
226   if (elapsed_timer_)
227     UMA_ENROLLMENT_TIME("Enterprise.EnrollmentTime.Cancel", elapsed_timer_);
228   if (enrollment_mode_ == EnrollmentScreenActor::ENROLLMENT_MODE_FORCED ||
229       enrollment_mode_ == EnrollmentScreenActor::ENROLLMENT_MODE_RECOVERY) {
230     actor_->ResetAuth(
231         base::Bind(&ScreenObserver::OnExit,
232                    base::Unretained(get_screen_observer()),
233                    ScreenObserver::ENTERPRISE_ENROLLMENT_BACK));
234     return;
235   }
236 
237   if (is_auto_enrollment())
238     policy::AutoEnrollmentClient::CancelAutoEnrollment();
239   actor_->ResetAuth(
240       base::Bind(&ScreenObserver::OnExit,
241                  base::Unretained(get_screen_observer()),
242                  ScreenObserver::ENTERPRISE_ENROLLMENT_COMPLETED));
243 }
244 
OnConfirmationClosed()245 void EnrollmentScreen::OnConfirmationClosed() {
246   // If the machine has been put in KIOSK mode we have to restart the session
247   // here to go in the proper KIOSK mode login screen.
248   policy::BrowserPolicyConnectorChromeOS* connector =
249       g_browser_process->platform_part()->browser_policy_connector_chromeos();
250   if (connector->GetDeviceMode() == policy::DEVICE_MODE_RETAIL_KIOSK) {
251     DBusThreadManager::Get()->GetSessionManagerClient()->StopSession();
252     return;
253   }
254 
255   if (is_auto_enrollment() &&
256       !enrollment_failed_once_ &&
257       !user_.empty() &&
258       LoginUtils::IsWhitelisted(user_, NULL)) {
259     actor_->ShowLoginSpinnerScreen();
260     get_screen_observer()->OnExit(
261         ScreenObserver::ENTERPRISE_AUTO_MAGIC_ENROLLMENT_COMPLETED);
262   } else {
263     actor_->ResetAuth(
264         base::Bind(&ScreenObserver::OnExit,
265                    base::Unretained(get_screen_observer()),
266                    ScreenObserver::ENTERPRISE_ENROLLMENT_COMPLETED));
267   }
268 }
269 
RegisterForDevicePolicy(const std::string & token)270 void EnrollmentScreen::RegisterForDevicePolicy(const std::string& token) {
271   policy::BrowserPolicyConnectorChromeOS* connector =
272       g_browser_process->platform_part()->browser_policy_connector_chromeos();
273   if (connector->IsEnterpriseManaged() &&
274       connector->GetEnterpriseDomain() != gaia::ExtractDomainName(user_)) {
275     LOG(ERROR) << "Trying to re-enroll to a different domain than "
276                << connector->GetEnterpriseDomain();
277     UMAFailure(policy::kMetricEnrollmentPrecheckDomainMismatch);
278     actor_->ShowUIError(
279         EnrollmentScreenActor::UI_ERROR_DOMAIN_MISMATCH);
280     return;
281   }
282 
283   policy::DeviceCloudPolicyInitializer::AllowedDeviceModes device_modes;
284   device_modes[policy::DEVICE_MODE_ENTERPRISE] = true;
285   device_modes[policy::DEVICE_MODE_RETAIL_KIOSK] =
286       enrollment_mode_ == EnrollmentScreenActor::ENROLLMENT_MODE_MANUAL;
287   connector->ScheduleServiceInitialization(0);
288 
289   policy::DeviceCloudPolicyInitializer* dcp_initializer =
290       connector->GetDeviceCloudPolicyInitializer();
291   CHECK(dcp_initializer);
292   dcp_initializer->StartEnrollment(
293       enterprise_management::PolicyData::ENTERPRISE_MANAGED,
294       connector->device_management_service(),
295       token, is_auto_enrollment(), device_modes,
296       base::Bind(&EnrollmentScreen::ReportEnrollmentStatus,
297                  weak_ptr_factory_.GetWeakPtr()));
298 }
299 
SendEnrollmentAuthToken(const std::string & token)300 void EnrollmentScreen::SendEnrollmentAuthToken(const std::string& token) {
301   // TODO(achuith, zork): Extract and send domain.
302   if (shark_controller_)
303     shark_controller_->OnAuthenticationDone("", token);
304 }
305 
ShowEnrollmentStatusOnSuccess(const policy::EnrollmentStatus & status)306 void EnrollmentScreen::ShowEnrollmentStatusOnSuccess(
307     const policy::EnrollmentStatus& status) {
308   StartupUtils::MarkOobeCompleted();
309   if (elapsed_timer_)
310     UMA_ENROLLMENT_TIME("Enterprise.EnrollmentTime.Success", elapsed_timer_);
311   actor_->ShowEnrollmentStatus(status);
312 }
313 
ReportEnrollmentStatus(policy::EnrollmentStatus status)314 void EnrollmentScreen::ReportEnrollmentStatus(policy::EnrollmentStatus status) {
315   switch (status.status()) {
316     case policy::EnrollmentStatus::STATUS_SUCCESS:
317       StartupUtils::MarkDeviceRegistered(
318           base::Bind(&EnrollmentScreen::ShowEnrollmentStatusOnSuccess,
319                      weak_ptr_factory_.GetWeakPtr(),
320                      status));
321       UMA(is_auto_enrollment() ? policy::kMetricEnrollmentAutoOK
322                                : policy::kMetricEnrollmentOK);
323       if (remora_controller_)
324         remora_controller_->SetEnrollmentComplete(true);
325       return;
326     case policy::EnrollmentStatus::STATUS_REGISTRATION_FAILED:
327     case policy::EnrollmentStatus::STATUS_POLICY_FETCH_FAILED:
328       switch (status.client_status()) {
329         case policy::DM_STATUS_SUCCESS:
330           NOTREACHED();
331           break;
332         case policy::DM_STATUS_REQUEST_INVALID:
333           UMAFailure(policy::kMetricEnrollmentRegisterPolicyPayloadInvalid);
334           break;
335         case policy::DM_STATUS_SERVICE_DEVICE_NOT_FOUND:
336           UMAFailure(policy::kMetricEnrollmentRegisterPolicyDeviceNotFound);
337           break;
338         case policy::DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID:
339           UMAFailure(policy::kMetricEnrollmentRegisterPolicyDMTokenInvalid);
340           break;
341         case policy::DM_STATUS_SERVICE_ACTIVATION_PENDING:
342           UMAFailure(policy::kMetricEnrollmentRegisterPolicyActivationPending);
343           break;
344         case policy::DM_STATUS_SERVICE_DEVICE_ID_CONFLICT:
345           UMAFailure(policy::kMetricEnrollmentRegisterPolicyDeviceIdConflict);
346           break;
347         case policy::DM_STATUS_SERVICE_POLICY_NOT_FOUND:
348           UMAFailure(policy::kMetricEnrollmentRegisterPolicyNotFound);
349           break;
350         case policy::DM_STATUS_REQUEST_FAILED:
351           UMAFailure(policy::kMetricEnrollmentRegisterPolicyRequestFailed);
352           break;
353         case policy::DM_STATUS_TEMPORARY_UNAVAILABLE:
354           UMAFailure(policy::kMetricEnrollmentRegisterPolicyTempUnavailable);
355           break;
356         case policy::DM_STATUS_HTTP_STATUS_ERROR:
357           UMAFailure(policy::kMetricEnrollmentRegisterPolicyHttpError);
358           break;
359         case policy::DM_STATUS_RESPONSE_DECODING_ERROR:
360           UMAFailure(policy::kMetricEnrollmentRegisterPolicyResponseInvalid);
361           break;
362         case policy::DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED:
363           UMAFailure(policy::kMetricEnrollmentNotSupported);
364           break;
365         case policy::DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER:
366           UMAFailure(policy::kMetricEnrollmentRegisterPolicyInvalidSerial);
367           break;
368         case policy::DM_STATUS_SERVICE_MISSING_LICENSES:
369           UMAFailure(policy::kMetricEnrollmentRegisterPolicyMissingLicenses);
370           break;
371         case policy::DM_STATUS_SERVICE_DEPROVISIONED:
372           UMAFailure(policy::kMetricEnrollmentRegisterPolicyDeprovisioned);
373           break;
374         case policy::DM_STATUS_SERVICE_DOMAIN_MISMATCH:
375           UMAFailure(policy::kMetricEnrollmentRegisterPolicyDomainMismatch);
376           break;
377       }
378       break;
379     case policy::EnrollmentStatus::STATUS_REGISTRATION_BAD_MODE:
380       UMAFailure(policy::kMetricEnrollmentInvalidEnrollmentMode);
381       break;
382     case policy::EnrollmentStatus::STATUS_LOCK_TIMEOUT:
383       UMAFailure(policy::kMetricEnrollmentLockboxTimeoutError);
384       break;
385     case policy::EnrollmentStatus::STATUS_LOCK_WRONG_USER:
386       UMAFailure(policy::kMetricEnrollmentLockDomainMismatch);
387       break;
388     case policy::EnrollmentStatus::STATUS_NO_STATE_KEYS:
389       UMAFailure(policy::kMetricEnrollmentNoStateKeys);
390       break;
391     case policy::EnrollmentStatus::STATUS_VALIDATION_FAILED:
392       UMAFailure(policy::kMetricEnrollmentPolicyValidationFailed);
393       break;
394     case policy::EnrollmentStatus::STATUS_STORE_ERROR:
395       UMAFailure(policy::kMetricEnrollmentCloudPolicyStoreError);
396       break;
397     case policy::EnrollmentStatus::STATUS_LOCK_ERROR:
398       UMAFailure(policy::kMetricEnrollmentLockBackendError);
399       break;
400     case policy::EnrollmentStatus::STATUS_ROBOT_AUTH_FETCH_FAILED:
401       UMAFailure(policy::kMetricEnrollmentRobotAuthCodeFetchFailed);
402       break;
403     case policy::EnrollmentStatus::STATUS_ROBOT_REFRESH_FETCH_FAILED:
404       UMAFailure(policy::kMetricEnrollmentRobotRefreshTokenFetchFailed);
405       break;
406     case policy::EnrollmentStatus::STATUS_ROBOT_REFRESH_STORE_FAILED:
407       UMAFailure(policy::kMetricEnrollmentRobotRefreshTokenStoreFailed);
408       break;
409     case policy::EnrollmentStatus::STATUS_STORE_TOKEN_AND_ID_FAILED:
410       // This error should not happen for enterprise enrollment, it only affects
411       // consumer enrollment.
412       UMAFailure(policy::kMetricEnrollmentStoreTokenAndIdFailed);
413       NOTREACHED();
414       break;
415   }
416 
417   if (remora_controller_)
418     remora_controller_->SetEnrollmentComplete(false);
419   enrollment_failed_once_ = true;
420   if (elapsed_timer_)
421     UMA_ENROLLMENT_TIME("Enterprise.EnrollmentTime.Failure", elapsed_timer_);
422   actor_->ShowEnrollmentStatus(status);
423 }
424 
UMA(policy::MetricEnrollment sample)425 void EnrollmentScreen::UMA(policy::MetricEnrollment sample) {
426   switch (enrollment_mode_) {
427     case EnrollmentScreenActor::ENROLLMENT_MODE_MANUAL:
428     case EnrollmentScreenActor::ENROLLMENT_MODE_AUTO:
429       UMA_HISTOGRAM_SPARSE_SLOWLY("Enterprise.Enrollment", sample);
430       break;
431     case EnrollmentScreenActor::ENROLLMENT_MODE_FORCED:
432       UMA_HISTOGRAM_SPARSE_SLOWLY("Enterprise.EnrollmentForced", sample);
433       break;
434     case EnrollmentScreenActor::ENROLLMENT_MODE_RECOVERY:
435       UMA_HISTOGRAM_SPARSE_SLOWLY("Enterprise.EnrollmentRecovery", sample);
436       break;
437     case EnrollmentScreenActor::ENROLLMENT_MODE_COUNT:
438       NOTREACHED();
439       break;
440   }
441 }
442 
UMAFailure(policy::MetricEnrollment sample)443 void EnrollmentScreen::UMAFailure(policy::MetricEnrollment sample) {
444   if (is_auto_enrollment())
445     sample = policy::kMetricEnrollmentAutoFailed;
446   UMA(sample);
447 }
448 
ShowSigninScreen()449 void EnrollmentScreen::ShowSigninScreen() {
450   actor_->Show();
451   actor_->ShowSigninScreen();
452 }
453 
454 }  // namespace chromeos
455