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/auto_enrollment_controller.h"
8 #include "base/bind_helpers.h"
9 #include "base/command_line.h"
10 #include "base/logging.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h"
14 #include "chromeos/chromeos_switches.h"
15 #include "components/policy/core/browser/browser_policy_connector.h"
16 #include "components/policy/core/common/cloud/device_management_service.h"
17 #include "net/url_request/url_request_context_getter.h"
23 // Returns the int value of the |switch_name| argument, clamped to the [0, 62]
24 // interval. Returns 0 if the argument doesn't exist or isn't an int value.
25 int GetSanitizedArg(const std::string& switch_name) {
26 CommandLine* command_line = CommandLine::ForCurrentProcess();
27 if (!command_line->HasSwitch(switch_name))
29 std::string value = command_line->GetSwitchValueASCII(switch_name);
31 if (!base::StringToInt(value, &int_value)) {
32 LOG(ERROR) << "Switch \"" << switch_name << "\" is not a valid int. "
33 << "Defaulting to 0.";
37 LOG(ERROR) << "Switch \"" << switch_name << "\" can't be negative. "
41 if (int_value > policy::AutoEnrollmentClient::kMaximumPower) {
42 LOG(ERROR) << "Switch \"" << switch_name << "\" can't be greater than "
43 << policy::AutoEnrollmentClient::kMaximumPower << ". Using "
44 << policy::AutoEnrollmentClient::kMaximumPower;
45 return policy::AutoEnrollmentClient::kMaximumPower;
52 const char AutoEnrollmentController::kForcedReEnrollmentAlways[] = "always";
53 const char AutoEnrollmentController::kForcedReEnrollmentLegacy[] = "legacy";
54 const char AutoEnrollmentController::kForcedReEnrollmentNever[] = "never";
55 const char AutoEnrollmentController::kForcedReEnrollmentOfficialBuild[] =
58 AutoEnrollmentController::Mode AutoEnrollmentController::GetMode() {
59 CommandLine* command_line = CommandLine::ForCurrentProcess();
61 if (!command_line->HasSwitch(switches::kEnterpriseEnableForcedReEnrollment))
62 return MODE_LEGACY_AUTO_ENROLLMENT;
64 std::string command_line_mode = command_line->GetSwitchValueASCII(
65 switches::kEnterpriseEnableForcedReEnrollment);
66 if (command_line_mode == kForcedReEnrollmentAlways) {
67 return MODE_FORCED_RE_ENROLLMENT;
68 } else if (command_line_mode.empty() ||
69 command_line_mode == kForcedReEnrollmentOfficialBuild) {
70 #if defined(OFFICIAL_BUILD)
71 return MODE_FORCED_RE_ENROLLMENT;
75 } else if (command_line_mode == kForcedReEnrollmentLegacy) {
76 return MODE_LEGACY_AUTO_ENROLLMENT;
82 AutoEnrollmentController::AutoEnrollmentController()
83 : state_(policy::AUTO_ENROLLMENT_STATE_IDLE),
84 weak_factory_(this) {}
86 AutoEnrollmentController::~AutoEnrollmentController() {}
88 void AutoEnrollmentController::Start() {
89 // This method is called at the point in the OOBE/login flow at which the
90 // auto-enrollment check can start. This happens either after the EULA is
91 // accepted, or right after a reboot if the EULA has already been accepted.
93 // Do not communicate auto-enrollment data to the server if
94 // 1. we are running integration or perf tests with telemetry.
95 // 2. modulus configuration is not present.
96 // 3. Auto-enrollment is disabled via the command line.
98 CommandLine* command_line = CommandLine::ForCurrentProcess();
99 if (command_line->HasSwitch(chromeos::switches::kOobeSkipPostLogin) ||
100 (!command_line->HasSwitch(
101 chromeos::switches::kEnterpriseEnrollmentInitialModulus) &&
102 !command_line->HasSwitch(
103 chromeos::switches::kEnterpriseEnrollmentModulusLimit)) ||
104 GetMode() == MODE_NONE) {
105 VLOG(1) << "Auto-enrollment disabled.";
106 UpdateState(policy::AUTO_ENROLLMENT_STATE_NO_ENROLLMENT);
110 // If there already is a client, bail out.
114 // Start by checking if the device has already been owned.
115 UpdateState(policy::AUTO_ENROLLMENT_STATE_PENDING);
116 weak_factory_.InvalidateWeakPtrs();
117 DeviceSettingsService::Get()->GetOwnershipStatusAsync(
118 base::Bind(&AutoEnrollmentController::OnOwnershipStatusCheckDone,
119 weak_factory_.GetWeakPtr()));
122 void AutoEnrollmentController::Cancel() {
124 // Cancelling the |client_| allows it to determine whether
125 // its protocol finished before login was complete.
126 client_.release()->CancelAndDeleteSoon();
130 void AutoEnrollmentController::Retry() {
135 scoped_ptr<AutoEnrollmentController::ProgressCallbackList::Subscription>
136 AutoEnrollmentController::RegisterProgressCallback(
137 const ProgressCallbackList::CallbackType& callback) {
138 return progress_callbacks_.Add(callback);
141 bool AutoEnrollmentController::ShouldEnrollSilently() {
142 return state_ == policy::AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT &&
143 GetMode() == MODE_LEGACY_AUTO_ENROLLMENT;
146 void AutoEnrollmentController::OnOwnershipStatusCheckDone(
147 DeviceSettingsService::OwnershipStatus status) {
148 if (status != DeviceSettingsService::OWNERSHIP_NONE) {
149 // The device is already owned. No need for auto-enrollment checks.
150 VLOG(1) << "Device already owned, skipping auto-enrollment check";
151 UpdateState(policy::AUTO_ENROLLMENT_STATE_NO_ENROLLMENT);
155 policy::BrowserPolicyConnector* connector =
156 g_browser_process->browser_policy_connector();
157 policy::DeviceManagementService* service =
158 connector->device_management_service();
159 service->ScheduleInitialization(0);
161 int power_initial = GetSanitizedArg(
162 chromeos::switches::kEnterpriseEnrollmentInitialModulus);
163 int power_limit = GetSanitizedArg(
164 chromeos::switches::kEnterpriseEnrollmentModulusLimit);
165 if (power_initial > power_limit) {
166 LOG(ERROR) << "Initial auto-enrollment modulus is larger than the limit, "
167 << "clamping to the limit.";
168 power_initial = power_limit;
171 bool retrieve_device_state = false;
172 std::string device_id;
173 if (GetMode() == MODE_FORCED_RE_ENROLLMENT) {
174 retrieve_device_state = true;
176 policy::DeviceCloudPolicyManagerChromeOS::GetCurrentDeviceStateKey();
178 device_id = policy::DeviceCloudPolicyManagerChromeOS::GetMachineID();
181 client_.reset(new policy::AutoEnrollmentClient(
182 base::Bind(&AutoEnrollmentController::UpdateState,
183 base::Unretained(this)),
185 g_browser_process->local_state(),
186 g_browser_process->system_request_context(),
188 retrieve_device_state,
192 VLOG(1) << "Starting auto-enrollment client.";
196 void AutoEnrollmentController::UpdateState(
197 policy::AutoEnrollmentState new_state) {
199 progress_callbacks_.Notify(state_);
202 } // namespace chromeos