ff6cc9ca37f864e76be95e0f9f1f292eb39fa79f
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / login / enrollment / auto_enrollment_controller.cc
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.
4
5 #include "chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.h"
6
7 #include "base/bind.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"
18
19 namespace chromeos {
20
21 namespace {
22
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))
28     return 0;
29   std::string value = command_line->GetSwitchValueASCII(switch_name);
30   int int_value;
31   if (!base::StringToInt(value, &int_value)) {
32     LOG(ERROR) << "Switch \"" << switch_name << "\" is not a valid int. "
33                << "Defaulting to 0.";
34     return 0;
35   }
36   if (int_value < 0) {
37     LOG(ERROR) << "Switch \"" << switch_name << "\" can't be negative. "
38                << "Using 0";
39     return 0;
40   }
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;
46   }
47   return int_value;
48 }
49
50 }  // namespace
51
52 const char AutoEnrollmentController::kForcedReEnrollmentAlways[] = "always";
53 const char AutoEnrollmentController::kForcedReEnrollmentLegacy[] = "legacy";
54 const char AutoEnrollmentController::kForcedReEnrollmentNever[] = "never";
55 const char AutoEnrollmentController::kForcedReEnrollmentOfficialBuild[] =
56     "official";
57
58 AutoEnrollmentController::Mode AutoEnrollmentController::GetMode() {
59   CommandLine* command_line = CommandLine::ForCurrentProcess();
60
61   if (!command_line->HasSwitch(switches::kEnterpriseEnableForcedReEnrollment))
62     return MODE_LEGACY_AUTO_ENROLLMENT;
63
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;
72 #else
73     return MODE_NONE;
74 #endif
75   } else if (command_line_mode == kForcedReEnrollmentLegacy) {
76     return MODE_LEGACY_AUTO_ENROLLMENT;
77   }
78
79   return MODE_NONE;
80 }
81
82 AutoEnrollmentController::AutoEnrollmentController()
83     : state_(policy::AUTO_ENROLLMENT_STATE_IDLE),
84       weak_factory_(this) {}
85
86 AutoEnrollmentController::~AutoEnrollmentController() {}
87
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.
92
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.
97
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);
107     return;
108   }
109
110   // If there already is a client, bail out.
111   if (client_)
112     return;
113
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()));
120 }
121
122 void AutoEnrollmentController::Cancel() {
123   if (client_) {
124     // Cancelling the |client_| allows it to determine whether
125     // its protocol finished before login was complete.
126     client_.release()->CancelAndDeleteSoon();
127   }
128 }
129
130 void AutoEnrollmentController::Retry() {
131   if (client_)
132     client_->Retry();
133 }
134
135 scoped_ptr<AutoEnrollmentController::ProgressCallbackList::Subscription>
136 AutoEnrollmentController::RegisterProgressCallback(
137     const ProgressCallbackList::CallbackType& callback) {
138   return progress_callbacks_.Add(callback);
139 }
140
141 bool AutoEnrollmentController::ShouldEnrollSilently() {
142   return state_ == policy::AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT &&
143          GetMode() == MODE_LEGACY_AUTO_ENROLLMENT;
144 }
145
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);
152     return;
153   }
154
155   policy::BrowserPolicyConnector* connector =
156       g_browser_process->browser_policy_connector();
157   policy::DeviceManagementService* service =
158       connector->device_management_service();
159   service->ScheduleInitialization(0);
160
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;
169   }
170
171   bool retrieve_device_state = false;
172   std::string device_id;
173   if (GetMode() == MODE_FORCED_RE_ENROLLMENT) {
174     retrieve_device_state = true;
175     device_id =
176         policy::DeviceCloudPolicyManagerChromeOS::GetCurrentDeviceStateKey();
177   } else {
178     device_id = policy::DeviceCloudPolicyManagerChromeOS::GetMachineID();
179   }
180
181   client_.reset(new policy::AutoEnrollmentClient(
182       base::Bind(&AutoEnrollmentController::UpdateState,
183                  base::Unretained(this)),
184       service,
185       g_browser_process->local_state(),
186       g_browser_process->system_request_context(),
187       device_id,
188       retrieve_device_state,
189       power_initial,
190       power_limit));
191
192   VLOG(1) << "Starting auto-enrollment client.";
193   client_->Start();
194 }
195
196 void AutoEnrollmentController::UpdateState(
197     policy::AutoEnrollmentState new_state) {
198   state_ = new_state;
199   progress_callbacks_.Notify(state_);
200 }
201
202 }  // namespace chromeos