1effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
2effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// found in the LICENSE file.
4effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
5effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.h"
6effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
7effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/bind.h"
8effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/bind_helpers.h"
9effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/command_line.h"
10effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/logging.h"
11effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/strings/string_number_conversions.h"
12effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "chrome/browser/browser_process.h"
13010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
14effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h"
15010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "chrome/browser/chromeos/policy/server_backed_state_keys_broker.h"
16effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "chromeos/chromeos_switches.h"
17effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "components/policy/core/common/cloud/device_management_service.h"
18effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "net/url_request/url_request_context_getter.h"
19effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
20effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochnamespace chromeos {
21effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
22effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochnamespace {
23effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
24effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Returns the int value of the |switch_name| argument, clamped to the [0, 62]
25effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// interval. Returns 0 if the argument doesn't exist or isn't an int value.
26effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochint GetSanitizedArg(const std::string& switch_name) {
27effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  CommandLine* command_line = CommandLine::ForCurrentProcess();
28effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (!command_line->HasSwitch(switch_name))
29effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return 0;
30effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  std::string value = command_line->GetSwitchValueASCII(switch_name);
31effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  int int_value;
32effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (!base::StringToInt(value, &int_value)) {
33effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    LOG(ERROR) << "Switch \"" << switch_name << "\" is not a valid int. "
34effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch               << "Defaulting to 0.";
35effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return 0;
36effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
37effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (int_value < 0) {
38effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    LOG(ERROR) << "Switch \"" << switch_name << "\" can't be negative. "
39effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch               << "Using 0";
40effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return 0;
41effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
42effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (int_value > policy::AutoEnrollmentClient::kMaximumPower) {
43effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    LOG(ERROR) << "Switch \"" << switch_name << "\" can't be greater than "
44effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch               << policy::AutoEnrollmentClient::kMaximumPower << ". Using "
45effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch               << policy::AutoEnrollmentClient::kMaximumPower;
46effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return policy::AutoEnrollmentClient::kMaximumPower;
47effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
48effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return int_value;
49effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
50effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
51effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}  // namespace
52effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
53c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochconst char AutoEnrollmentController::kForcedReEnrollmentAlways[] = "always";
54c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochconst char AutoEnrollmentController::kForcedReEnrollmentLegacy[] = "legacy";
55c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochconst char AutoEnrollmentController::kForcedReEnrollmentNever[] = "never";
56c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochconst char AutoEnrollmentController::kForcedReEnrollmentOfficialBuild[] =
57c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    "official";
58c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
59c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochAutoEnrollmentController::Mode AutoEnrollmentController::GetMode() {
60c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  CommandLine* command_line = CommandLine::ForCurrentProcess();
61c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
62c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!command_line->HasSwitch(switches::kEnterpriseEnableForcedReEnrollment))
63c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return MODE_LEGACY_AUTO_ENROLLMENT;
64c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
65c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  std::string command_line_mode = command_line->GetSwitchValueASCII(
66c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      switches::kEnterpriseEnableForcedReEnrollment);
67c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (command_line_mode == kForcedReEnrollmentAlways) {
68c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return MODE_FORCED_RE_ENROLLMENT;
69c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  } else if (command_line_mode.empty() ||
70c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch             command_line_mode == kForcedReEnrollmentOfficialBuild) {
71c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#if defined(OFFICIAL_BUILD)
72c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return MODE_FORCED_RE_ENROLLMENT;
73c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#else
74c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return MODE_NONE;
75c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#endif
76c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  } else if (command_line_mode == kForcedReEnrollmentLegacy) {
77c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return MODE_LEGACY_AUTO_ENROLLMENT;
78c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
79c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
80c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return MODE_NONE;
81c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
82c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
83effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochAutoEnrollmentController::AutoEnrollmentController()
84effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    : state_(policy::AUTO_ENROLLMENT_STATE_IDLE),
85010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      client_start_weak_factory_(this) {}
86effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
87effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochAutoEnrollmentController::~AutoEnrollmentController() {}
88effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
89effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid AutoEnrollmentController::Start() {
90effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // This method is called at the point in the OOBE/login flow at which the
91effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // auto-enrollment check can start. This happens either after the EULA is
92effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // accepted, or right after a reboot if the EULA has already been accepted.
93effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
94effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Do not communicate auto-enrollment data to the server if
95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // 1. we are running telemetry tests.
96effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // 2. modulus configuration is not present.
97c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // 3. Auto-enrollment is disabled via the command line.
98c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
99effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  CommandLine* command_line = CommandLine::ForCurrentProcess();
100116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (command_line->HasSwitch(chromeos::switches::kDisableGaiaServices) ||
101effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      (!command_line->HasSwitch(
102effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch           chromeos::switches::kEnterpriseEnrollmentInitialModulus) &&
103effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch       !command_line->HasSwitch(
104c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch           chromeos::switches::kEnterpriseEnrollmentModulusLimit)) ||
105c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      GetMode() == MODE_NONE) {
106effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    VLOG(1) << "Auto-enrollment disabled.";
107effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    UpdateState(policy::AUTO_ENROLLMENT_STATE_NO_ENROLLMENT);
108effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return;
109effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
110effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
111010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // If a client is being created or already existing, bail out.
112010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (client_start_weak_factory_.HasWeakPtrs() || client_)
113effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return;
114effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
115effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Start by checking if the device has already been owned.
116effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  UpdateState(policy::AUTO_ENROLLMENT_STATE_PENDING);
117effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DeviceSettingsService::Get()->GetOwnershipStatusAsync(
118effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      base::Bind(&AutoEnrollmentController::OnOwnershipStatusCheckDone,
119010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 client_start_weak_factory_.GetWeakPtr()));
120effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
121effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
122effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid AutoEnrollmentController::Cancel() {
123effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (client_) {
124effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // Cancelling the |client_| allows it to determine whether
125effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // its protocol finished before login was complete.
126effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    client_.release()->CancelAndDeleteSoon();
127effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
128010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
129010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Make sure to nuke pending |client_| start sequences.
130010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  client_start_weak_factory_.InvalidateWeakPtrs();
131effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
132effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
133effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid AutoEnrollmentController::Retry() {
134effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (client_)
135effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    client_->Retry();
136effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
137effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
138effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochscoped_ptr<AutoEnrollmentController::ProgressCallbackList::Subscription>
139effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochAutoEnrollmentController::RegisterProgressCallback(
140effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const ProgressCallbackList::CallbackType& callback) {
141effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return progress_callbacks_.Add(callback);
142effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
143effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
144effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool AutoEnrollmentController::ShouldEnrollSilently() {
145c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return state_ == policy::AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT &&
146c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch         GetMode() == MODE_LEGACY_AUTO_ENROLLMENT;
147effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
148effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
149effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid AutoEnrollmentController::OnOwnershipStatusCheckDone(
150effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    DeviceSettingsService::OwnershipStatus status) {
151effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (status != DeviceSettingsService::OWNERSHIP_NONE) {
152effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // The device is already owned. No need for auto-enrollment checks.
153effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    VLOG(1) << "Device already owned, skipping auto-enrollment check";
154effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    UpdateState(policy::AUTO_ENROLLMENT_STATE_NO_ENROLLMENT);
155effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return;
156effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
157effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
158010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Make sure state keys are available.
159010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  g_browser_process->platform_part()
160010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      ->browser_policy_connector_chromeos()
161010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      ->GetStateKeysBroker()
162010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      ->RequestStateKeys(base::Bind(&AutoEnrollmentController::StartClient,
163010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                    client_start_weak_factory_.GetWeakPtr()));
164010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
165010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
166010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void AutoEnrollmentController::StartClient(
16703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const std::vector<std::string>& state_keys, bool first_boot) {
168010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  policy::BrowserPolicyConnectorChromeOS* connector =
169010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      g_browser_process->platform_part()->browser_policy_connector_chromeos();
170effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  policy::DeviceManagementService* service =
171effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      connector->device_management_service();
172effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  service->ScheduleInitialization(0);
173effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
174effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  int power_initial = GetSanitizedArg(
175effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      chromeos::switches::kEnterpriseEnrollmentInitialModulus);
176effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  int power_limit = GetSanitizedArg(
177effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      chromeos::switches::kEnterpriseEnrollmentModulusLimit);
178effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (power_initial > power_limit) {
179effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    LOG(ERROR) << "Initial auto-enrollment modulus is larger than the limit, "
180effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch               << "clamping to the limit.";
181effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    power_initial = power_limit;
182effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
183effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
184effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  bool retrieve_device_state = false;
185effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  std::string device_id;
186c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (GetMode() == MODE_FORCED_RE_ENROLLMENT) {
187effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    retrieve_device_state = true;
18803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (!state_keys.empty() && !first_boot)
18903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      device_id = state_keys.front();
190effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  } else {
191effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    device_id = policy::DeviceCloudPolicyManagerChromeOS::GetMachineID();
192effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
193effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
194effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  client_.reset(new policy::AutoEnrollmentClient(
195effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      base::Bind(&AutoEnrollmentController::UpdateState,
196effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                 base::Unretained(this)),
197effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      service,
198effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      g_browser_process->local_state(),
199effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      g_browser_process->system_request_context(),
200effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      device_id,
201effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      retrieve_device_state,
202effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      power_initial,
203effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      power_limit));
204effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
205effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  VLOG(1) << "Starting auto-enrollment client.";
206effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  client_->Start();
207effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
208effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
209effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid AutoEnrollmentController::UpdateState(
210effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    policy::AutoEnrollmentState new_state) {
2116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  VLOG(1) << "New state: " << new_state << ".";
212effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  state_ = new_state;
213effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  progress_callbacks_.Notify(state_);
214effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
215effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
216effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}  // namespace chromeos
217