1 // Copyright 2014 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/enterprise_enrollment_helper_impl.h"
8 #include "base/location.h"
9 #include "base/logging.h"
10 #include "base/message_loop/message_loop.h"
11 #include "chrome/browser/browser_process.h"
12 #include "chrome/browser/browser_process_platform_part.h"
13 #include "chrome/browser/browsing_data/browsing_data_helper.h"
14 #include "chrome/browser/chromeos/login/enrollment/enrollment_uma.h"
15 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
16 #include "chrome/browser/chromeos/policy/device_cloud_policy_initializer.h"
17 #include "chrome/browser/chromeos/policy/enrollment_status_chromeos.h"
18 #include "chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
21 #include "google_apis/gaia/gaia_auth_consumer.h"
22 #include "google_apis/gaia/gaia_auth_fetcher.h"
23 #include "google_apis/gaia/gaia_constants.h"
27 // A helper class that takes care of asynchronously revoking a given token.
28 class TokenRevoker
: public GaiaAuthConsumer
{
31 ~TokenRevoker() override
;
33 void Start(const std::string
& token
);
36 void OnOAuth2RevokeTokenCompleted() override
;
39 GaiaAuthFetcher gaia_fetcher_
;
41 DISALLOW_COPY_AND_ASSIGN(TokenRevoker
);
44 TokenRevoker::TokenRevoker()
46 GaiaConstants::kChromeOSSource
,
47 g_browser_process
->system_request_context()) {
50 TokenRevoker::~TokenRevoker() {
53 void TokenRevoker::Start(const std::string
& token
) {
54 gaia_fetcher_
.StartRevokeOAuth2Token(token
);
57 void TokenRevoker::OnOAuth2RevokeTokenCompleted() {
58 base::MessageLoop::current()->DeleteSoon(FROM_HERE
, this);
65 EnterpriseEnrollmentHelperImpl::EnterpriseEnrollmentHelperImpl(
66 EnrollmentStatusConsumer
* status_consumer
,
67 const policy::EnrollmentConfig
& enrollment_config
,
68 const std::string
& enrolling_user_domain
)
69 : EnterpriseEnrollmentHelper(status_consumer
),
70 enrollment_config_(enrollment_config
),
71 enrolling_user_domain_(enrolling_user_domain
),
73 fetch_additional_token_(false),
75 oauth_fetchers_finished_(0),
76 last_auth_error_(GoogleServiceAuthError::AuthErrorNone()),
79 auth_data_cleared_(false),
80 browsing_data_remover_(NULL
),
81 weak_ptr_factory_(this) {
84 EnterpriseEnrollmentHelperImpl::~EnterpriseEnrollmentHelperImpl() {
85 DCHECK(g_browser_process
->IsShuttingDown() || !started_
||
86 (finished_
&& (success_
|| !profile_
|| auth_data_cleared_
)));
87 if (browsing_data_remover_
)
88 browsing_data_remover_
->RemoveObserver(this);
91 void EnterpriseEnrollmentHelperImpl::EnrollUsingProfile(
93 bool fetch_additional_token
) {
97 fetch_additional_token_
= fetch_additional_token
;
98 oauth_fetchers_
.resize(fetch_additional_token_
? 2 : 1);
99 for (size_t i
= 0; i
< oauth_fetchers_
.size(); ++i
) {
100 oauth_fetchers_
[i
] = new policy::PolicyOAuth2TokenFetcher(
101 profile_
->GetRequestContext(),
102 g_browser_process
->system_request_context(),
103 base::Bind(&EnterpriseEnrollmentHelperImpl::OnTokenFetched
,
104 weak_ptr_factory_
.GetWeakPtr(),
106 oauth_fetchers_
[i
]->Start();
110 void EnterpriseEnrollmentHelperImpl::EnrollUsingToken(
111 const std::string
& token
) {
114 DoEnrollUsingToken(token
);
117 void EnterpriseEnrollmentHelperImpl::ClearAuth(const base::Closure
& callback
) {
122 auth_clear_callbacks_
.push_back(callback
);
123 if (browsing_data_remover_
)
126 for (size_t i
= 0; i
< oauth_fetchers_
.size(); ++i
) {
127 // Do not revoke the additional token if enrollment has finished
129 if (i
== 1 && success_
)
132 if (!oauth_fetchers_
[i
]->oauth2_access_token().empty())
133 (new TokenRevoker())->Start(oauth_fetchers_
[i
]->oauth2_access_token());
135 if (!oauth_fetchers_
[i
]->oauth2_refresh_token().empty())
136 (new TokenRevoker())->Start(oauth_fetchers_
[i
]->oauth2_refresh_token());
138 oauth_fetchers_
.clear();
140 browsing_data_remover_
=
141 BrowsingDataRemover::CreateForUnboundedRange(profile_
);
142 browsing_data_remover_
->AddObserver(this);
143 browsing_data_remover_
->Remove(BrowsingDataRemover::REMOVE_SITE_DATA
,
144 BrowsingDataHelper::UNPROTECTED_WEB
);
147 void EnterpriseEnrollmentHelperImpl::DoEnrollUsingToken(
148 const std::string
& token
) {
149 policy::BrowserPolicyConnectorChromeOS
* connector
=
150 g_browser_process
->platform_part()->browser_policy_connector_chromeos();
151 if (connector
->IsEnterpriseManaged() &&
152 connector
->GetEnterpriseDomain() != enrolling_user_domain_
) {
153 LOG(ERROR
) << "Trying to re-enroll to a different domain than "
154 << connector
->GetEnterpriseDomain();
155 UMA(policy::kMetricEnrollmentPrecheckDomainMismatch
);
157 status_consumer()->OnOtherError(OTHER_ERROR_DOMAIN_MISMATCH
);
161 policy::DeviceCloudPolicyInitializer::AllowedDeviceModes device_modes
;
162 device_modes
[policy::DEVICE_MODE_ENTERPRISE
] = true;
163 connector
->ScheduleServiceInitialization(0);
165 policy::DeviceCloudPolicyInitializer
* dcp_initializer
=
166 connector
->GetDeviceCloudPolicyInitializer();
167 CHECK(dcp_initializer
);
168 dcp_initializer
->StartEnrollment(
169 policy::MANAGEMENT_MODE_ENTERPRISE_MANAGED
,
170 connector
->device_management_service(),
171 nullptr /* owner_settings_service */, enrollment_config_
, token
,
173 base::Bind(&EnterpriseEnrollmentHelperImpl::OnEnrollmentFinished
,
174 weak_ptr_factory_
.GetWeakPtr()));
177 void EnterpriseEnrollmentHelperImpl::OnTokenFetched(
178 size_t fetcher_index
,
179 const std::string
& token
,
180 const GoogleServiceAuthError
& error
) {
181 CHECK_LT(fetcher_index
, oauth_fetchers_
.size());
183 if (error
.state() != GoogleServiceAuthError::NONE
)
184 last_auth_error_
= error
;
186 ++oauth_fetchers_finished_
;
187 if (oauth_fetchers_finished_
!= oauth_fetchers_
.size())
190 if (last_auth_error_
.state() != GoogleServiceAuthError::NONE
) {
191 ReportAuthStatus(last_auth_error_
);
193 status_consumer()->OnAuthError(last_auth_error_
);
197 if (oauth_fetchers_
.size() == 2)
198 additional_token_
= oauth_fetchers_
[1]->oauth2_access_token();
199 DoEnrollUsingToken(oauth_fetchers_
[0]->oauth2_access_token());
202 void EnterpriseEnrollmentHelperImpl::OnEnrollmentFinished(
203 policy::EnrollmentStatus status
) {
204 ReportEnrollmentStatus(status
);
206 if (status
.status() == policy::EnrollmentStatus::STATUS_SUCCESS
) {
208 DCHECK(!fetch_additional_token_
|| !additional_token_
.empty());
209 status_consumer()->OnDeviceEnrolled(additional_token_
);
211 status_consumer()->OnEnrollmentError(status
);
215 void EnterpriseEnrollmentHelperImpl::ReportAuthStatus(
216 const GoogleServiceAuthError
& error
) {
217 switch (error
.state()) {
218 case GoogleServiceAuthError::NONE
:
219 case GoogleServiceAuthError::CAPTCHA_REQUIRED
:
220 case GoogleServiceAuthError::TWO_FACTOR
:
221 case GoogleServiceAuthError::HOSTED_NOT_ALLOWED
:
222 case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS
:
223 case GoogleServiceAuthError::REQUEST_CANCELED
:
224 case GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE
:
225 case GoogleServiceAuthError::SERVICE_ERROR
:
226 case GoogleServiceAuthError::WEB_LOGIN_REQUIRED
:
227 UMA(policy::kMetricEnrollmentLoginFailed
);
228 LOG(ERROR
) << "Auth error " << error
.state();
230 case GoogleServiceAuthError::USER_NOT_SIGNED_UP
:
231 UMA(policy::kMetricEnrollmentAccountNotSignedUp
);
232 LOG(ERROR
) << "Account not signed up " << error
.state();
234 case GoogleServiceAuthError::ACCOUNT_DELETED
:
235 UMA(policy::kMetricEnrollmentAccountDeleted
);
236 LOG(ERROR
) << "Account deleted " << error
.state();
238 case GoogleServiceAuthError::ACCOUNT_DISABLED
:
239 UMA(policy::kMetricEnrollmentAccountDisabled
);
240 LOG(ERROR
) << "Account disabled " << error
.state();
242 case GoogleServiceAuthError::CONNECTION_FAILED
:
243 case GoogleServiceAuthError::SERVICE_UNAVAILABLE
:
244 UMA(policy::kMetricEnrollmentNetworkFailed
);
245 LOG(WARNING
) << "Network error " << error
.state();
247 case GoogleServiceAuthError::NUM_STATES
:
253 void EnterpriseEnrollmentHelperImpl::ReportEnrollmentStatus(
254 policy::EnrollmentStatus status
) {
255 switch (status
.status()) {
256 case policy::EnrollmentStatus::STATUS_SUCCESS
:
257 UMA(policy::kMetricEnrollmentOK
);
259 case policy::EnrollmentStatus::STATUS_REGISTRATION_FAILED
:
260 case policy::EnrollmentStatus::STATUS_POLICY_FETCH_FAILED
:
261 switch (status
.client_status()) {
262 case policy::DM_STATUS_SUCCESS
:
265 case policy::DM_STATUS_REQUEST_INVALID
:
266 UMA(policy::kMetricEnrollmentRegisterPolicyPayloadInvalid
);
268 case policy::DM_STATUS_SERVICE_DEVICE_NOT_FOUND
:
269 UMA(policy::kMetricEnrollmentRegisterPolicyDeviceNotFound
);
271 case policy::DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID
:
272 UMA(policy::kMetricEnrollmentRegisterPolicyDMTokenInvalid
);
274 case policy::DM_STATUS_SERVICE_ACTIVATION_PENDING
:
275 UMA(policy::kMetricEnrollmentRegisterPolicyActivationPending
);
277 case policy::DM_STATUS_SERVICE_DEVICE_ID_CONFLICT
:
278 UMA(policy::kMetricEnrollmentRegisterPolicyDeviceIdConflict
);
280 case policy::DM_STATUS_SERVICE_POLICY_NOT_FOUND
:
281 UMA(policy::kMetricEnrollmentRegisterPolicyNotFound
);
283 case policy::DM_STATUS_REQUEST_FAILED
:
284 UMA(policy::kMetricEnrollmentRegisterPolicyRequestFailed
);
286 case policy::DM_STATUS_TEMPORARY_UNAVAILABLE
:
287 UMA(policy::kMetricEnrollmentRegisterPolicyTempUnavailable
);
289 case policy::DM_STATUS_HTTP_STATUS_ERROR
:
290 UMA(policy::kMetricEnrollmentRegisterPolicyHttpError
);
292 case policy::DM_STATUS_RESPONSE_DECODING_ERROR
:
293 UMA(policy::kMetricEnrollmentRegisterPolicyResponseInvalid
);
295 case policy::DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED
:
296 UMA(policy::kMetricEnrollmentNotSupported
);
298 case policy::DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER
:
299 UMA(policy::kMetricEnrollmentRegisterPolicyInvalidSerial
);
301 case policy::DM_STATUS_SERVICE_MISSING_LICENSES
:
302 UMA(policy::kMetricEnrollmentRegisterPolicyMissingLicenses
);
304 case policy::DM_STATUS_SERVICE_DEPROVISIONED
:
305 UMA(policy::kMetricEnrollmentRegisterPolicyDeprovisioned
);
307 case policy::DM_STATUS_SERVICE_DOMAIN_MISMATCH
:
308 UMA(policy::kMetricEnrollmentRegisterPolicyDomainMismatch
);
312 case policy::EnrollmentStatus::STATUS_REGISTRATION_BAD_MODE
:
313 UMA(policy::kMetricEnrollmentInvalidEnrollmentMode
);
315 case policy::EnrollmentStatus::STATUS_NO_STATE_KEYS
:
316 UMA(policy::kMetricEnrollmentNoStateKeys
);
318 case policy::EnrollmentStatus::STATUS_VALIDATION_FAILED
:
319 UMA(policy::kMetricEnrollmentPolicyValidationFailed
);
321 case policy::EnrollmentStatus::STATUS_STORE_ERROR
:
322 UMA(policy::kMetricEnrollmentCloudPolicyStoreError
);
324 case policy::EnrollmentStatus::STATUS_LOCK_ERROR
:
325 switch (status
.lock_status()) {
326 case policy::EnterpriseInstallAttributes::LOCK_SUCCESS
:
327 case policy::EnterpriseInstallAttributes::LOCK_NOT_READY
:
330 case policy::EnterpriseInstallAttributes::LOCK_TIMEOUT
:
331 UMA(policy::kMetricEnrollmentLockboxTimeoutError
);
333 case policy::EnterpriseInstallAttributes::LOCK_BACKEND_INVALID
:
334 UMA(policy::kMetricEnrollmentLockBackendInvalid
);
336 case policy::EnterpriseInstallAttributes::LOCK_ALREADY_LOCKED
:
337 UMA(policy::kMetricEnrollmentLockAlreadyLocked
);
339 case policy::EnterpriseInstallAttributes::LOCK_SET_ERROR
:
340 UMA(policy::kMetricEnrollmentLockSetError
);
342 case policy::EnterpriseInstallAttributes::LOCK_FINALIZE_ERROR
:
343 UMA(policy::kMetricEnrollmentLockFinalizeError
);
345 case policy::EnterpriseInstallAttributes::LOCK_READBACK_ERROR
:
346 UMA(policy::kMetricEnrollmentLockReadbackError
);
348 case policy::EnterpriseInstallAttributes::LOCK_WRONG_DOMAIN
:
349 UMA(policy::kMetricEnrollmentLockDomainMismatch
);
353 case policy::EnrollmentStatus::STATUS_ROBOT_AUTH_FETCH_FAILED
:
354 UMA(policy::kMetricEnrollmentRobotAuthCodeFetchFailed
);
356 case policy::EnrollmentStatus::STATUS_ROBOT_REFRESH_FETCH_FAILED
:
357 UMA(policy::kMetricEnrollmentRobotRefreshTokenFetchFailed
);
359 case policy::EnrollmentStatus::STATUS_ROBOT_REFRESH_STORE_FAILED
:
360 UMA(policy::kMetricEnrollmentRobotRefreshTokenStoreFailed
);
362 case policy::EnrollmentStatus::STATUS_STORE_TOKEN_AND_ID_FAILED
:
363 // This error should not happen for enterprise enrollment, it only affects
364 // consumer enrollment.
365 UMA(policy::kMetricEnrollmentStoreTokenAndIdFailed
);
371 void EnterpriseEnrollmentHelperImpl::UMA(policy::MetricEnrollment sample
) {
372 EnrollmentUMA(sample
, enrollment_config_
.mode
);
375 void EnterpriseEnrollmentHelperImpl::OnBrowsingDataRemoverDone() {
376 browsing_data_remover_
->RemoveObserver(this);
377 browsing_data_remover_
= NULL
;
378 auth_data_cleared_
= true;
380 std::vector
<base::Closure
> callbacks_to_run
;
381 callbacks_to_run
.swap(auth_clear_callbacks_
);
382 for (std::vector
<base::Closure
>::iterator
callback(callbacks_to_run
.begin());
383 callback
!= callbacks_to_run
.end();
389 } // namespace chromeos