15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/policy/enrollment_handler_chromeos.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/command_line.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
109ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/browser_process.h"
12010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.h"
14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
15116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/browser/chromeos/policy/server_backed_state_keys_broker.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/settings/device_oauth2_token_service.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/settings/device_oauth2_token_service_factory.h"
185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/chromeos/settings/device_settings_service.h"
19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chromeos/chromeos_switches.h"
20a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/cloud/cloud_policy_constants.h"
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "google_apis/gaia/gaia_urls.h"
221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "net/http/http_status_code.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace em = enterprise_management;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace policy {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Retry for InstallAttrs initialization every 500ms.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kLockRetryIntervalMs = 500;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Maximum time to retry InstallAttrs initialization before we give up.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kLockRetryTimeoutMs = 10 * 60 * 1000;  // 10 minutes.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Testing token used when the enrollment-skip-robot-auth is set to skip talking
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// to GAIA for an actual token. This is needed to be able to run against the
37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// testing DMServer implementations.
38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const char kTestingRobotToken[] = "test-token";
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EnrollmentHandlerChromeOS::EnrollmentHandlerChromeOS(
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DeviceCloudPolicyStoreChromeOS* store,
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EnterpriseInstallAttributes* install_attributes,
45010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    ServerBackedStateKeysBroker* state_keys_broker,
465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    chromeos::DeviceSettingsService* device_settings_service,
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<CloudPolicyClient> client,
488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    scoped_refptr<base::SequencedTaskRunner> background_task_runner,
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& auth_token,
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& client_id,
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool is_auto_enrollment,
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const std::string& requisition,
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const AllowedDeviceModes& allowed_device_modes,
545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    em::PolicyData::ManagementMode management_mode,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const EnrollmentCallback& completion_callback)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : store_(store),
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      install_attributes_(install_attributes),
58010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      state_keys_broker_(state_keys_broker),
595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      device_settings_service_(device_settings_service),
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      client_(client.Pass()),
618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      background_task_runner_(background_task_runner),
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      auth_token_(auth_token),
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      client_id_(client_id),
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      is_auto_enrollment_(is_auto_enrollment),
6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      requisition_(requisition),
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      allowed_device_modes_(allowed_device_modes),
675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      management_mode_(management_mode),
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      completion_callback_(completion_callback),
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      device_mode_(DEVICE_MODE_NOT_SET),
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      enrollment_step_(STEP_PENDING),
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lockbox_init_duration_(0),
721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      weak_ptr_factory_(this) {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(!client_->is_registered());
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_EQ(DM_STATUS_SUCCESS, client_->status());
755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  CHECK(management_mode_ == em::PolicyData::ENTERPRISE_MANAGED ||
765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        management_mode_ == em::PolicyData::CONSUMER_MANAGED);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  store_->AddObserver(this);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_->AddObserver(this);
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  client_->AddNamespaceToFetch(PolicyNamespaceKey(
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      dm_protocol::kChromeDevicePolicyType, std::string()));
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EnrollmentHandlerChromeOS::~EnrollmentHandlerChromeOS() {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Stop();
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  store_->RemoveObserver(this);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnrollmentHandlerChromeOS::StartEnrollment() {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_EQ(STEP_PENDING, enrollment_step_);
90010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  enrollment_step_ = STEP_STATE_KEYS;
91010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  state_keys_broker_->RequestStateKeys(
921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(&EnrollmentHandlerChromeOS::HandleStateKeysResult,
93010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_ptr<CloudPolicyClient> EnrollmentHandlerChromeOS::ReleaseClient() {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Stop();
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return client_.Pass();
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnrollmentHandlerChromeOS::OnPolicyFetched(CloudPolicyClient* client) {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(client_.get(), client);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_EQ(STEP_POLICY_FETCH, enrollment_step_);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enrollment_step_ = STEP_VALIDATION;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Validate the policy.
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const em::PolicyFetchResponse* policy = client_->GetPolicyFor(
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PolicyNamespaceKey(dm_protocol::kChromeDevicePolicyType, std::string()));
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!policy) {
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ReportResult(EnrollmentStatus::ForFetchError(
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        DM_STATUS_RESPONSE_DECODING_ERROR));
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<DeviceCloudPolicyValidator> validator(
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DeviceCloudPolicyValidator::Create(
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          scoped_ptr<em::PolicyFetchResponse>(
1198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)              new em::PolicyFetchResponse(*policy)),
1208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          background_task_runner_));
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  validator->ValidateTimestamp(base::Time(), base::Time::NowFromSystemTime(),
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               CloudPolicyValidatorBase::TIMESTAMP_REQUIRED);
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // If this is re-enrollment, make sure that the new policy matches the
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // previously-enrolled domain.
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string domain;
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (install_attributes_->IsEnterpriseDevice()) {
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    domain = install_attributes_->GetDomain();
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    validator->ValidateDomain(domain);
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  validator->ValidateDMToken(client->dm_token(),
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             CloudPolicyValidatorBase::DM_TOKEN_REQUIRED);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  validator->ValidatePolicyType(dm_protocol::kChromeDevicePolicyType);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  validator->ValidatePayload();
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // If |domain| is empty here, the policy validation code will just use the
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // domain from the username field in the policy itself to do key validation.
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // TODO(mnissler): Plumb the enrolling user's username into this object so
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // we can validate the username on the resulting policy, and use the domain
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // from that username to validate the key below (http://crbug.com/343074).
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  validator->ValidateInitialKey(GetPolicyVerificationKey(), domain);
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  validator.release()->StartValidation(
1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(&EnrollmentHandlerChromeOS::HandlePolicyValidationResult,
1441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnrollmentHandlerChromeOS::OnRegistrationStateChanged(
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloudPolicyClient* client) {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(client_.get(), client);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (enrollment_step_ == STEP_REGISTRATION && client_->is_registered()) {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enrollment_step_ = STEP_POLICY_FETCH,
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    device_mode_ = client_->device_mode();
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (device_mode_ == DEVICE_MODE_NOT_SET)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      device_mode_ = DEVICE_MODE_ENTERPRISE;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!allowed_device_modes_.test(device_mode_)) {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Bad device mode " << device_mode_;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ReportResult(EnrollmentStatus::ForStatus(
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          EnrollmentStatus::STATUS_REGISTRATION_BAD_MODE));
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    client_->FetchPolicy();
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(FATAL) << "Registration state changed to " << client_->is_registered()
1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci               << " in step " << enrollment_step_ << ".";
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnrollmentHandlerChromeOS::OnClientError(CloudPolicyClient* client) {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(client_.get(), client);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (enrollment_step_ == STEP_ROBOT_AUTH_FETCH) {
1731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    LOG(ERROR) << "API authentication code fetch failed: "
1741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)               << client_->status();
1751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    ReportResult(EnrollmentStatus::ForRobotAuthFetchError(client_->status()));
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else if (enrollment_step_ < STEP_POLICY_FETCH) {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReportResult(EnrollmentStatus::ForRegistrationError(client_->status()));
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReportResult(EnrollmentStatus::ForFetchError(client_->status()));
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnrollmentHandlerChromeOS::OnStoreLoaded(CloudPolicyStore* store) {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(store_, store);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (enrollment_step_ == STEP_LOADING_STORE) {
1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // If the |store_| wasn't initialized when StartEnrollment() was called,
1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // then StartRegistration() bails silently. This gets registration rolling
1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // again after the store finishes loading.
1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    StartRegistration();
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (enrollment_step_ == STEP_STORE_POLICY) {
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReportResult(EnrollmentStatus::ForStatus(EnrollmentStatus::STATUS_SUCCESS));
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnrollmentHandlerChromeOS::OnStoreError(CloudPolicyStore* store) {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(store_, store);
1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (enrollment_step_ == STEP_STORE_TOKEN_AND_ID) {
1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Calling DeviceSettingsService::SetManagementSettings() on a non-
2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // enterprise-managed device will trigger OnStoreError(), as
2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // DeviceCloudPolicyStore listens to all changes on DeviceSettingsService,
2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // and it calls OnStoreError() when the device is not enterprise-managed.
2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportResult(EnrollmentStatus::ForStoreError(store_->status(),
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               store_->validation_status()));
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EnrollmentHandlerChromeOS::HandleStateKeysResult(
21003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const std::vector<std::string>& state_keys, bool /* first_boot */) {
211010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  CHECK_EQ(STEP_STATE_KEYS, enrollment_step_);
212010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
213010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Make sure state keys are available if forced re-enrollment is on.
214010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (chromeos::AutoEnrollmentController::GetMode() ==
215010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      chromeos::AutoEnrollmentController::MODE_FORCED_RE_ENROLLMENT) {
2161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    client_->SetStateKeysToUpload(state_keys);
2171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    current_state_key_ = state_keys_broker_->current_state_key();
2181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (state_keys.empty() || current_state_key_.empty()) {
219010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      ReportResult(
220010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          EnrollmentStatus::ForStatus(EnrollmentStatus::STATUS_NO_STATE_KEYS));
221010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return;
222010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
223010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
224010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
225010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  enrollment_step_ = STEP_LOADING_STORE;
2261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  StartRegistration();
227010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
228010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
2291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EnrollmentHandlerChromeOS::StartRegistration() {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_EQ(STEP_LOADING_STORE, enrollment_step_);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (store_->is_initialized()) {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enrollment_step_ = STEP_REGISTRATION;
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    client_->Register(em::DeviceRegisterRequest::DEVICE,
23490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                      auth_token_, client_id_, is_auto_enrollment_,
235effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                      requisition_, current_state_key_);
2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } else {
2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Do nothing. StartRegistration() will be called again from OnStoreLoaded()
2381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // after the CloudPolicyStore has initialized.
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EnrollmentHandlerChromeOS::HandlePolicyValidationResult(
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DeviceCloudPolicyValidator* validator) {
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_EQ(STEP_VALIDATION, enrollment_step_);
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (validator->success()) {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    policy_ = validator->policy().Pass();
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    username_ = validator->policy_data()->username();
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    device_id_ = validator->policy_data()->device_id();
2495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    request_token_ = validator->policy_data()->request_token();
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
251f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (CommandLine::ForCurrentProcess()->HasSwitch(
252f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            chromeos::switches::kEnterpriseEnrollmentSkipRobotAuth)) {
253f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // For test purposes we allow enrollment to succeed without proper robot
254f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // account and use the provided value as a token.
255f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      refresh_token_ = kTestingRobotToken;
2565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      enrollment_step_ = STEP_LOCK_DEVICE;
2575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      StartLockDevice();
258f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return;
259f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
260f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    enrollment_step_ = STEP_ROBOT_AUTH_FETCH;
262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    client_->FetchRobotAuthCodes(auth_token_);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReportResult(EnrollmentStatus::ForValidationError(validator->status()));
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EnrollmentHandlerChromeOS::OnRobotAuthCodesFetched(
269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CloudPolicyClient* client) {
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK_EQ(client_.get(), client);
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_EQ(STEP_ROBOT_AUTH_FETCH, enrollment_step_);
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  enrollment_step_ = STEP_ROBOT_AUTH_REFRESH;
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gaia::OAuthClientInfo client_info;
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  client_info.client_id = GaiaUrls::GetInstance()->oauth2_chrome_client_id();
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  client_info.client_secret =
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GaiaUrls::GetInstance()->oauth2_chrome_client_secret();
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  client_info.redirect_uri = "oob";
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Use the system request context to avoid sending user cookies.
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gaia_oauth_client_.reset(new gaia::GaiaOAuthClient(
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      g_browser_process->system_request_context()));
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gaia_oauth_client_->GetTokensFromAuthCode(client_info,
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                            client->robot_api_auth_code(),
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                            0 /* max_retries */,
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                            this);
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// GaiaOAuthClient::Delegate callback for OAuth2 refresh token fetched.
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EnrollmentHandlerChromeOS::OnGetTokensResponse(
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& refresh_token,
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& access_token,
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int expires_in_seconds) {
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_EQ(STEP_ROBOT_AUTH_REFRESH, enrollment_step_);
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  refresh_token_ = refresh_token;
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  enrollment_step_ = STEP_LOCK_DEVICE;
3005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  StartLockDevice();
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// GaiaOAuthClient::Delegate
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EnrollmentHandlerChromeOS::OnRefreshTokenResponse(
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& access_token,
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int expires_in_seconds) {
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // We never use the code that should trigger this callback.
3081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  LOG(FATAL) << "Unexpected callback invoked.";
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// GaiaOAuthClient::Delegate OAuth2 error when fetching refresh token request.
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EnrollmentHandlerChromeOS::OnOAuthError() {
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_EQ(STEP_ROBOT_AUTH_REFRESH, enrollment_step_);
3141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // OnOAuthError is only called if the request is bad (malformed) or the
3151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // response is bad (empty access token returned).
3161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  LOG(ERROR) << "OAuth protocol error while fetching API refresh token.";
3171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  ReportResult(
3181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      EnrollmentStatus::ForRobotRefreshFetchError(net::HTTP_BAD_REQUEST));
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// GaiaOAuthClient::Delegate network error when fetching refresh token.
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EnrollmentHandlerChromeOS::OnNetworkError(int response_code) {
3231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  CHECK_EQ(STEP_ROBOT_AUTH_REFRESH, enrollment_step_);
324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LOG(ERROR) << "Network error while fetching API refresh token: "
325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             << response_code;
3261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  ReportResult(
3271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      EnrollmentStatus::ForRobotRefreshFetchError(response_code));
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void EnrollmentHandlerChromeOS::StartLockDevice() {
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_EQ(STEP_LOCK_DEVICE, enrollment_step_);
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Since this method is also called directly.
3331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  weak_ptr_factory_.InvalidateWeakPtrs();
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (management_mode_ == em::PolicyData::CONSUMER_MANAGED) {
3365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Consumer device enrollment doesn't use install attributes. Instead,
3375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // we put the information in the owners settings.
3385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    enrollment_step_ = STEP_STORE_TOKEN_AND_ID;
3395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    device_settings_service_->SetManagementSettings(
3405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        management_mode_, request_token_, device_id_,
3411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        base::Bind(&EnrollmentHandlerChromeOS::HandleSetManagementSettingsDone,
3425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
3435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  } else {
3445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    install_attributes_->LockDevice(
3455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        username_, device_mode_, device_id_,
3465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        base::Bind(&EnrollmentHandlerChromeOS::HandleLockDeviceResult,
3475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
3485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
3495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
3505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EnrollmentHandlerChromeOS::HandleSetManagementSettingsDone() {
3525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  CHECK_EQ(STEP_STORE_TOKEN_AND_ID, enrollment_step_);
3535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (device_settings_service_->status() !=
3545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      chromeos::DeviceSettingsService::STORE_SUCCESS) {
3555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ReportResult(EnrollmentStatus::ForStatus(
3565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        EnrollmentStatus::STATUS_STORE_TOKEN_AND_ID_FAILED));
3575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
3585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
3595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  StartStoreRobotAuth();
361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EnrollmentHandlerChromeOS::HandleLockDeviceResult(
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EnterpriseInstallAttributes::LockResult lock_result) {
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_EQ(STEP_LOCK_DEVICE, enrollment_step_);
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (lock_result) {
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EnterpriseInstallAttributes::LOCK_SUCCESS:
3681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      StartStoreRobotAuth();
3691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      break;
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EnterpriseInstallAttributes::LOCK_NOT_READY:
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We wait up to |kLockRetryTimeoutMs| milliseconds and if it hasn't
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // succeeded by then show an error to the user and stop the enrollment.
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (lockbox_init_duration_ < kLockRetryTimeoutMs) {
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // InstallAttributes not ready yet, retry later.
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(WARNING) << "Install Attributes not ready yet will retry in "
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     << kLockRetryIntervalMs << "ms.";
37790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        base::MessageLoop::current()->PostDelayedTask(
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            FROM_HERE,
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            base::Bind(&EnrollmentHandlerChromeOS::StartLockDevice,
3805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                       weak_ptr_factory_.GetWeakPtr()),
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            base::TimeDelta::FromMilliseconds(kLockRetryIntervalMs));
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        lockbox_init_duration_ += kLockRetryIntervalMs;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ReportResult(EnrollmentStatus::ForStatus(
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            EnrollmentStatus::STATUS_LOCK_TIMEOUT));
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      break;
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EnterpriseInstallAttributes::LOCK_BACKEND_ERROR:
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ReportResult(EnrollmentStatus::ForStatus(
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          EnrollmentStatus::STATUS_LOCK_ERROR));
3911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      break;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EnterpriseInstallAttributes::LOCK_WRONG_USER:
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Enrollment cannot proceed because the InstallAttrs "
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << "has been locked already!";
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ReportResult(EnrollmentStatus::ForStatus(
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          EnrollmentStatus::STATUS_LOCK_WRONG_USER));
3971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      break;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EnrollmentHandlerChromeOS::StartStoreRobotAuth() {
4025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Get the token service so we can store our robot refresh token.
4035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  enrollment_step_ = STEP_STORE_ROBOT_AUTH;
4045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  chromeos::DeviceOAuth2TokenServiceFactory::Get()->SetAndSaveRefreshToken(
4055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      refresh_token_,
4061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(&EnrollmentHandlerChromeOS::HandleStoreRobotAuthTokenResult,
4075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
4085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
4095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EnrollmentHandlerChromeOS::HandleStoreRobotAuthTokenResult(bool result) {
4111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  CHECK_EQ(STEP_STORE_ROBOT_AUTH, enrollment_step_);
4121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
413a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!result) {
4141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    LOG(ERROR) << "Failed to store API refresh token.";
4151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    ReportResult(EnrollmentStatus::ForStatus(
4161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        EnrollmentStatus::STATUS_ROBOT_REFRESH_STORE_FAILED));
4171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return;
4181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
4191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (management_mode_ == em::PolicyData::CONSUMER_MANAGED) {
4215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // For consumer management enrollment, we don't store the policy.
4225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ReportResult(EnrollmentStatus::ForStatus(EnrollmentStatus::STATUS_SUCCESS));
4235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
4245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
4255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  enrollment_step_ = STEP_STORE_POLICY;
4271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  store_->InstallInitialPolicy(*policy_);
4281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
4291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnrollmentHandlerChromeOS::Stop() {
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (client_.get())
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    client_->RemoveObserver(this);
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enrollment_step_ = STEP_FINISHED;
4341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  weak_ptr_factory_.InvalidateWeakPtrs();
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  completion_callback_.Reset();
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnrollmentHandlerChromeOS::ReportResult(EnrollmentStatus status) {
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnrollmentCallback callback = completion_callback_;
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Stop();
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (status.status() != EnrollmentStatus::STATUS_SUCCESS) {
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Enrollment failed: " << status.status()
4441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 << ", client: " << status.client_status()
4451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 << ", validation: " << status.validation_status()
4461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 << ", store: " << status.store_status();
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!callback.is_null())
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback.Run(status);
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace policy
454