Fix the duplicatedly commited composition text when switching IME.
[chromium-blink-merge.git] / chrome / browser / chromeos / policy / enrollment_handler_chromeos.cc
blobbf8e1f13752327a39bb407b4736ad35c5e923f39
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/policy/enrollment_handler_chromeos.h"
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h"
10 #include "chrome/browser/browser_process.h"
11 #include "chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.h"
12 #include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h"
13 #include "chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.h"
14 #include "chrome/browser/chromeos/policy/enrollment_status_chromeos.h"
15 #include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
16 #include "chrome/browser/chromeos/policy/server_backed_state_keys_broker.h"
17 #include "chrome/browser/chromeos/profiles/profile_helper.h"
18 #include "chrome/browser/chromeos/settings/device_oauth2_token_service.h"
19 #include "chrome/browser/chromeos/settings/device_oauth2_token_service_factory.h"
20 #include "chrome/browser/profiles/profile.h"
21 #include "google_apis/gaia/gaia_urls.h"
22 #include "net/http/http_status_code.h"
24 namespace em = enterprise_management;
26 namespace policy {
28 namespace {
30 // Retry for InstallAttrs initialization every 500ms.
31 const int kLockRetryIntervalMs = 500;
32 // Maximum time to retry InstallAttrs initialization before we give up.
33 const int kLockRetryTimeoutMs = 10 * 60 * 1000; // 10 minutes.
35 em::DeviceRegisterRequest::Flavor EnrollmentModeToRegistrationFlavor(
36 policy::EnrollmentConfig::Mode mode) {
37 switch (mode) {
38 case policy::EnrollmentConfig::MODE_NONE:
39 break;
40 case policy::EnrollmentConfig::MODE_MANUAL:
41 return em::DeviceRegisterRequest::FLAVOR_ENROLLMENT_MANUAL;
42 case policy::EnrollmentConfig::MODE_MANUAL_REENROLLMENT:
43 return em::DeviceRegisterRequest::FLAVOR_ENROLLMENT_MANUAL_RENEW;
44 case policy::EnrollmentConfig::MODE_LOCAL_FORCED:
45 return em::DeviceRegisterRequest::FLAVOR_ENROLLMENT_LOCAL_FORCED;
46 case policy::EnrollmentConfig::MODE_LOCAL_ADVERTISED:
47 return em::DeviceRegisterRequest::FLAVOR_ENROLLMENT_LOCAL_ADVERTISED;
48 case policy::EnrollmentConfig::MODE_SERVER_FORCED:
49 return em::DeviceRegisterRequest::FLAVOR_ENROLLMENT_SERVER_FORCED;
50 case policy::EnrollmentConfig::MODE_SERVER_ADVERTISED:
51 return em::DeviceRegisterRequest::FLAVOR_ENROLLMENT_SERVER_ADVERTISED;
52 case policy::EnrollmentConfig::MODE_RECOVERY:
53 return em::DeviceRegisterRequest::FLAVOR_ENROLLMENT_RECOVERY;
56 NOTREACHED() << "Bad enrollment mode: " << mode;
57 return em::DeviceRegisterRequest::FLAVOR_ENROLLMENT_MANUAL;
60 } // namespace
62 EnrollmentHandlerChromeOS::EnrollmentHandlerChromeOS(
63 DeviceCloudPolicyStoreChromeOS* store,
64 EnterpriseInstallAttributes* install_attributes,
65 ServerBackedStateKeysBroker* state_keys_broker,
66 chromeos::OwnerSettingsServiceChromeOS* owner_settings_service,
67 scoped_ptr<CloudPolicyClient> client,
68 scoped_refptr<base::SequencedTaskRunner> background_task_runner,
69 const EnrollmentConfig& enrollment_config,
70 const std::string& auth_token,
71 const std::string& client_id,
72 const std::string& requisition,
73 const AllowedDeviceModes& allowed_device_modes,
74 ManagementMode management_mode,
75 const EnrollmentCallback& completion_callback)
76 : store_(store),
77 install_attributes_(install_attributes),
78 state_keys_broker_(state_keys_broker),
79 owner_settings_service_(owner_settings_service),
80 client_(client.Pass()),
81 background_task_runner_(background_task_runner),
82 enrollment_config_(enrollment_config),
83 auth_token_(auth_token),
84 client_id_(client_id),
85 requisition_(requisition),
86 allowed_device_modes_(allowed_device_modes),
87 management_mode_(management_mode),
88 completion_callback_(completion_callback),
89 device_mode_(DEVICE_MODE_NOT_SET),
90 skip_robot_auth_(false),
91 enrollment_step_(STEP_PENDING),
92 lockbox_init_duration_(0),
93 weak_ptr_factory_(this) {
94 CHECK(!client_->is_registered());
95 CHECK_EQ(DM_STATUS_SUCCESS, client_->status());
96 CHECK(management_mode_ == MANAGEMENT_MODE_ENTERPRISE_MANAGED ||
97 management_mode_ == MANAGEMENT_MODE_CONSUMER_MANAGED);
98 store_->AddObserver(this);
99 client_->AddObserver(this);
100 client_->AddPolicyTypeToFetch(dm_protocol::kChromeDevicePolicyType,
101 std::string());
104 EnrollmentHandlerChromeOS::~EnrollmentHandlerChromeOS() {
105 Stop();
106 store_->RemoveObserver(this);
109 void EnrollmentHandlerChromeOS::StartEnrollment() {
110 CHECK_EQ(STEP_PENDING, enrollment_step_);
111 enrollment_step_ = STEP_STATE_KEYS;
112 state_keys_broker_->RequestStateKeys(
113 base::Bind(&EnrollmentHandlerChromeOS::HandleStateKeysResult,
114 weak_ptr_factory_.GetWeakPtr()));
117 scoped_ptr<CloudPolicyClient> EnrollmentHandlerChromeOS::ReleaseClient() {
118 Stop();
119 return client_.Pass();
122 void EnrollmentHandlerChromeOS::OnPolicyFetched(CloudPolicyClient* client) {
123 DCHECK_EQ(client_.get(), client);
124 CHECK_EQ(STEP_POLICY_FETCH, enrollment_step_);
126 enrollment_step_ = STEP_VALIDATION;
128 // Validate the policy.
129 const em::PolicyFetchResponse* policy = client_->GetPolicyFor(
130 dm_protocol::kChromeDevicePolicyType, std::string());
131 if (!policy) {
132 ReportResult(EnrollmentStatus::ForFetchError(
133 DM_STATUS_RESPONSE_DECODING_ERROR));
134 return;
137 scoped_ptr<DeviceCloudPolicyValidator> validator(
138 DeviceCloudPolicyValidator::Create(
139 scoped_ptr<em::PolicyFetchResponse>(
140 new em::PolicyFetchResponse(*policy)),
141 background_task_runner_));
143 validator->ValidateTimestamp(base::Time(), base::Time::NowFromSystemTime(),
144 CloudPolicyValidatorBase::TIMESTAMP_REQUIRED);
146 // If this is re-enrollment, make sure that the new policy matches the
147 // previously-enrolled domain.
148 std::string domain;
149 if (install_attributes_->IsEnterpriseDevice()) {
150 domain = install_attributes_->GetDomain();
151 validator->ValidateDomain(domain);
153 validator->ValidateDMToken(client->dm_token(),
154 CloudPolicyValidatorBase::DM_TOKEN_REQUIRED);
155 validator->ValidatePolicyType(dm_protocol::kChromeDevicePolicyType);
156 validator->ValidatePayload();
157 if (management_mode_ == MANAGEMENT_MODE_CONSUMER_MANAGED) {
158 // For consumer-managed devices, although we don't store the policy, we
159 // still need to verify its integrity since we use the request token in it.
160 // The consumer device management server does not have the verification
161 // key, and we need to skip checking on that by passing an empty key to
162 // ValidateInitialKey(). ValidateInitialKey() still checks that the policy
163 // data is correctly signed by the new public key when the verification key
164 // is empty.
165 validator->ValidateInitialKey(std::string(), std::string());
166 } else {
167 // If |domain| is empty here, the policy validation code will just use the
168 // domain from the username field in the policy itself to do key validation.
169 // TODO(mnissler): Plumb the enrolling user's username into this object so
170 // we can validate the username on the resulting policy, and use the domain
171 // from that username to validate the key below (http://crbug.com/343074).
172 validator->ValidateInitialKey(GetPolicyVerificationKey(), domain);
174 validator.release()->StartValidation(
175 base::Bind(&EnrollmentHandlerChromeOS::HandlePolicyValidationResult,
176 weak_ptr_factory_.GetWeakPtr()));
179 void EnrollmentHandlerChromeOS::OnRegistrationStateChanged(
180 CloudPolicyClient* client) {
181 DCHECK_EQ(client_.get(), client);
183 if (enrollment_step_ == STEP_REGISTRATION && client_->is_registered()) {
184 enrollment_step_ = STEP_POLICY_FETCH,
185 device_mode_ = client_->device_mode();
186 if (device_mode_ == DEVICE_MODE_NOT_SET)
187 device_mode_ = DEVICE_MODE_ENTERPRISE;
188 if (!allowed_device_modes_.test(device_mode_)) {
189 LOG(ERROR) << "Bad device mode " << device_mode_;
190 ReportResult(EnrollmentStatus::ForStatus(
191 EnrollmentStatus::STATUS_REGISTRATION_BAD_MODE));
192 return;
194 client_->FetchPolicy();
195 } else {
196 LOG(FATAL) << "Registration state changed to " << client_->is_registered()
197 << " in step " << enrollment_step_ << ".";
201 void EnrollmentHandlerChromeOS::OnClientError(CloudPolicyClient* client) {
202 DCHECK_EQ(client_.get(), client);
204 if (enrollment_step_ == STEP_ROBOT_AUTH_FETCH) {
205 LOG(ERROR) << "API authentication code fetch failed: "
206 << client_->status();
207 ReportResult(EnrollmentStatus::ForRobotAuthFetchError(client_->status()));
208 } else if (enrollment_step_ < STEP_POLICY_FETCH) {
209 ReportResult(EnrollmentStatus::ForRegistrationError(client_->status()));
210 } else {
211 ReportResult(EnrollmentStatus::ForFetchError(client_->status()));
215 void EnrollmentHandlerChromeOS::OnStoreLoaded(CloudPolicyStore* store) {
216 DCHECK_EQ(store_, store);
218 if (enrollment_step_ == STEP_LOADING_STORE) {
219 // If the |store_| wasn't initialized when StartEnrollment() was called,
220 // then StartRegistration() bails silently. This gets registration rolling
221 // again after the store finishes loading.
222 StartRegistration();
223 } else if (enrollment_step_ == STEP_STORE_POLICY) {
224 ReportResult(EnrollmentStatus::ForStatus(EnrollmentStatus::STATUS_SUCCESS));
228 void EnrollmentHandlerChromeOS::OnStoreError(CloudPolicyStore* store) {
229 DCHECK_EQ(store_, store);
230 if (enrollment_step_ == STEP_STORE_TOKEN_AND_ID) {
231 // Calling OwnerSettingsServiceChromeOS::SetManagementSettings()
232 // on a non- enterprise-managed device will fail as
233 // DeviceCloudPolicyStore listens to all changes on device
234 // settings, and it calls OnStoreError() when the device is not
235 // enterprise-managed.
236 return;
238 ReportResult(EnrollmentStatus::ForStoreError(store_->status(),
239 store_->validation_status()));
242 void EnrollmentHandlerChromeOS::HandleStateKeysResult(
243 const std::vector<std::string>& state_keys) {
244 CHECK_EQ(STEP_STATE_KEYS, enrollment_step_);
246 // Make sure state keys are available if forced re-enrollment is on.
247 if (chromeos::AutoEnrollmentController::GetMode() ==
248 chromeos::AutoEnrollmentController::MODE_FORCED_RE_ENROLLMENT) {
249 client_->SetStateKeysToUpload(state_keys);
250 current_state_key_ = state_keys_broker_->current_state_key();
251 if (state_keys.empty() || current_state_key_.empty()) {
252 ReportResult(
253 EnrollmentStatus::ForStatus(EnrollmentStatus::STATUS_NO_STATE_KEYS));
254 return;
258 enrollment_step_ = STEP_LOADING_STORE;
259 StartRegistration();
262 void EnrollmentHandlerChromeOS::StartRegistration() {
263 CHECK_EQ(STEP_LOADING_STORE, enrollment_step_);
264 if (store_->is_initialized()) {
265 enrollment_step_ = STEP_REGISTRATION;
266 client_->Register(
267 em::DeviceRegisterRequest::DEVICE,
268 EnrollmentModeToRegistrationFlavor(enrollment_config_.mode),
269 auth_token_, client_id_, requisition_, current_state_key_);
270 } else {
271 // Do nothing. StartRegistration() will be called again from OnStoreLoaded()
272 // after the CloudPolicyStore has initialized.
276 void EnrollmentHandlerChromeOS::HandlePolicyValidationResult(
277 DeviceCloudPolicyValidator* validator) {
278 CHECK_EQ(STEP_VALIDATION, enrollment_step_);
279 if (validator->success()) {
280 policy_ = validator->policy().Pass();
281 username_ = validator->policy_data()->username();
282 device_id_ = validator->policy_data()->device_id();
283 request_token_ = validator->policy_data()->request_token();
284 enrollment_step_ = STEP_ROBOT_AUTH_FETCH;
285 client_->FetchRobotAuthCodes(auth_token_);
286 } else {
287 ReportResult(EnrollmentStatus::ForValidationError(validator->status()));
291 void EnrollmentHandlerChromeOS::OnRobotAuthCodesFetched(
292 CloudPolicyClient* client) {
293 DCHECK_EQ(client_.get(), client);
294 CHECK_EQ(STEP_ROBOT_AUTH_FETCH, enrollment_step_);
296 if (client->robot_api_auth_code().empty()) {
297 // If the server doesn't provide an auth code, skip the robot auth setup.
298 // This allows clients running against the test server to transparently skip
299 // robot auth.
300 skip_robot_auth_ = true;
301 enrollment_step_ = STEP_LOCK_DEVICE;
302 StartLockDevice();
303 return;
306 enrollment_step_ = STEP_ROBOT_AUTH_REFRESH;
308 gaia::OAuthClientInfo client_info;
309 client_info.client_id = GaiaUrls::GetInstance()->oauth2_chrome_client_id();
310 client_info.client_secret =
311 GaiaUrls::GetInstance()->oauth2_chrome_client_secret();
312 client_info.redirect_uri = "oob";
314 // Use the system request context to avoid sending user cookies.
315 gaia_oauth_client_.reset(new gaia::GaiaOAuthClient(
316 g_browser_process->system_request_context()));
317 gaia_oauth_client_->GetTokensFromAuthCode(client_info,
318 client->robot_api_auth_code(),
319 0 /* max_retries */,
320 this);
323 // GaiaOAuthClient::Delegate callback for OAuth2 refresh token fetched.
324 void EnrollmentHandlerChromeOS::OnGetTokensResponse(
325 const std::string& refresh_token,
326 const std::string& access_token,
327 int expires_in_seconds) {
328 CHECK_EQ(STEP_ROBOT_AUTH_REFRESH, enrollment_step_);
330 robot_refresh_token_ = refresh_token;
332 enrollment_step_ = STEP_LOCK_DEVICE;
333 StartLockDevice();
336 // GaiaOAuthClient::Delegate
337 void EnrollmentHandlerChromeOS::OnRefreshTokenResponse(
338 const std::string& access_token,
339 int expires_in_seconds) {
340 // We never use the code that should trigger this callback.
341 LOG(FATAL) << "Unexpected callback invoked.";
344 // GaiaOAuthClient::Delegate OAuth2 error when fetching refresh token request.
345 void EnrollmentHandlerChromeOS::OnOAuthError() {
346 CHECK_EQ(STEP_ROBOT_AUTH_REFRESH, enrollment_step_);
347 // OnOAuthError is only called if the request is bad (malformed) or the
348 // response is bad (empty access token returned).
349 LOG(ERROR) << "OAuth protocol error while fetching API refresh token.";
350 ReportResult(
351 EnrollmentStatus::ForRobotRefreshFetchError(net::HTTP_BAD_REQUEST));
354 // GaiaOAuthClient::Delegate network error when fetching refresh token.
355 void EnrollmentHandlerChromeOS::OnNetworkError(int response_code) {
356 CHECK_EQ(STEP_ROBOT_AUTH_REFRESH, enrollment_step_);
357 LOG(ERROR) << "Network error while fetching API refresh token: "
358 << response_code;
359 ReportResult(
360 EnrollmentStatus::ForRobotRefreshFetchError(response_code));
363 void EnrollmentHandlerChromeOS::StartLockDevice() {
364 CHECK_EQ(STEP_LOCK_DEVICE, enrollment_step_);
365 // Since this method is also called directly.
366 weak_ptr_factory_.InvalidateWeakPtrs();
368 if (management_mode_ == MANAGEMENT_MODE_CONSUMER_MANAGED) {
369 CHECK(owner_settings_service_);
371 // Consumer device enrollment doesn't use install attributes. Instead,
372 // we put the information in the owners settings.
373 enrollment_step_ = STEP_STORE_TOKEN_AND_ID;
374 chromeos::OwnerSettingsServiceChromeOS::ManagementSettings settings;
375 settings.management_mode = management_mode_;
376 settings.request_token = request_token_;
377 settings.device_id = device_id_;
378 owner_settings_service_->SetManagementSettings(
379 settings,
380 base::Bind(&EnrollmentHandlerChromeOS::HandleSetManagementSettingsDone,
381 weak_ptr_factory_.GetWeakPtr()));
382 } else {
383 install_attributes_->LockDevice(
384 username_, device_mode_, device_id_,
385 base::Bind(&EnrollmentHandlerChromeOS::HandleLockDeviceResult,
386 weak_ptr_factory_.GetWeakPtr()));
390 void EnrollmentHandlerChromeOS::HandleSetManagementSettingsDone(bool success) {
391 CHECK_EQ(STEP_STORE_TOKEN_AND_ID, enrollment_step_);
392 if (!success) {
393 ReportResult(EnrollmentStatus::ForStatus(
394 EnrollmentStatus::STATUS_STORE_TOKEN_AND_ID_FAILED));
395 return;
398 StartStoreRobotAuth();
401 void EnrollmentHandlerChromeOS::HandleLockDeviceResult(
402 EnterpriseInstallAttributes::LockResult lock_result) {
403 CHECK_EQ(STEP_LOCK_DEVICE, enrollment_step_);
404 switch (lock_result) {
405 case EnterpriseInstallAttributes::LOCK_SUCCESS:
406 StartStoreRobotAuth();
407 break;
408 case EnterpriseInstallAttributes::LOCK_NOT_READY:
409 // We wait up to |kLockRetryTimeoutMs| milliseconds and if it hasn't
410 // succeeded by then show an error to the user and stop the enrollment.
411 if (lockbox_init_duration_ < kLockRetryTimeoutMs) {
412 // InstallAttributes not ready yet, retry later.
413 LOG(WARNING) << "Install Attributes not ready yet will retry in "
414 << kLockRetryIntervalMs << "ms.";
415 base::MessageLoop::current()->PostDelayedTask(
416 FROM_HERE,
417 base::Bind(&EnrollmentHandlerChromeOS::StartLockDevice,
418 weak_ptr_factory_.GetWeakPtr()),
419 base::TimeDelta::FromMilliseconds(kLockRetryIntervalMs));
420 lockbox_init_duration_ += kLockRetryIntervalMs;
421 } else {
422 HandleLockDeviceResult(EnterpriseInstallAttributes::LOCK_TIMEOUT);
424 break;
425 case EnterpriseInstallAttributes::LOCK_TIMEOUT:
426 case EnterpriseInstallAttributes::LOCK_BACKEND_INVALID:
427 case EnterpriseInstallAttributes::LOCK_ALREADY_LOCKED:
428 case EnterpriseInstallAttributes::LOCK_SET_ERROR:
429 case EnterpriseInstallAttributes::LOCK_FINALIZE_ERROR:
430 case EnterpriseInstallAttributes::LOCK_READBACK_ERROR:
431 case EnterpriseInstallAttributes::LOCK_WRONG_DOMAIN:
432 case EnterpriseInstallAttributes::LOCK_WRONG_MODE:
433 ReportResult(EnrollmentStatus::ForLockError(lock_result));
434 break;
438 void EnrollmentHandlerChromeOS::StartStoreRobotAuth() {
439 enrollment_step_ = STEP_STORE_ROBOT_AUTH;
441 // Don't store the token if robot auth was skipped.
442 if (skip_robot_auth_) {
443 HandleStoreRobotAuthTokenResult(true);
444 return;
447 chromeos::DeviceOAuth2TokenServiceFactory::Get()->SetAndSaveRefreshToken(
448 robot_refresh_token_,
449 base::Bind(&EnrollmentHandlerChromeOS::HandleStoreRobotAuthTokenResult,
450 weak_ptr_factory_.GetWeakPtr()));
453 void EnrollmentHandlerChromeOS::HandleStoreRobotAuthTokenResult(bool result) {
454 CHECK_EQ(STEP_STORE_ROBOT_AUTH, enrollment_step_);
456 if (!result) {
457 LOG(ERROR) << "Failed to store API refresh token.";
458 ReportResult(EnrollmentStatus::ForStatus(
459 EnrollmentStatus::STATUS_ROBOT_REFRESH_STORE_FAILED));
460 return;
463 if (management_mode_ == MANAGEMENT_MODE_CONSUMER_MANAGED) {
464 // For consumer management enrollment, we don't store the policy.
465 ReportResult(EnrollmentStatus::ForStatus(EnrollmentStatus::STATUS_SUCCESS));
466 return;
469 enrollment_step_ = STEP_STORE_POLICY;
470 store_->InstallInitialPolicy(*policy_);
473 void EnrollmentHandlerChromeOS::Stop() {
474 if (client_.get())
475 client_->RemoveObserver(this);
476 enrollment_step_ = STEP_FINISHED;
477 weak_ptr_factory_.InvalidateWeakPtrs();
478 completion_callback_.Reset();
481 void EnrollmentHandlerChromeOS::ReportResult(EnrollmentStatus status) {
482 EnrollmentCallback callback = completion_callback_;
483 Stop();
485 if (status.status() != EnrollmentStatus::STATUS_SUCCESS) {
486 LOG(WARNING) << "Enrollment failed: " << status.status()
487 << ", client: " << status.client_status()
488 << ", validation: " << status.validation_status()
489 << ", store: " << status.store_status()
490 << ", lock: " << status.lock_status();
493 if (!callback.is_null())
494 callback.Run(status);
497 } // namespace policy