device_cloud_policy_manager_chromeos.cc revision f2477e01787aa58f445919b809d89e252beef54f
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.
4
5#include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h"
6
7#include "base/bind.h"
8#include "base/bind_helpers.h"
9#include "base/prefs/pref_registry_simple.h"
10#include "base/prefs/pref_service.h"
11#include "chrome/browser/chromeos/attestation/attestation_policy_observer.h"
12#include "chrome/browser/chromeos/login/startup_utils.h"
13#include "chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.h"
14#include "chrome/browser/chromeos/policy/enrollment_handler_chromeos.h"
15#include "chrome/browser/chromeos/policy/enterprise_install_attributes.h"
16#include "chrome/browser/policy/cloud/cloud_policy_constants.h"
17#include "chrome/browser/policy/cloud/cloud_policy_store.h"
18#include "chrome/browser/policy/cloud/device_management_service.h"
19#include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h"
20#include "chrome/common/pref_names.h"
21#include "chromeos/chromeos_constants.h"
22#include "chromeos/system/statistics_provider.h"
23#include "content/public/browser/browser_thread.h"
24
25using content::BrowserThread;
26
27namespace em = enterprise_management;
28
29namespace policy {
30
31namespace {
32
33// MachineInfo key names.
34const char kMachineInfoSystemHwqual[] = "hardware_class";
35
36// These are the machine serial number keys that we check in order until we
37// find a non-empty serial number. The VPD spec says the serial number should be
38// in the "serial_number" key for v2+ VPDs. However, legacy devices used a
39// different keys to report their serial number, which we fall back to if
40// "serial_number" is not present.
41//
42// Product_S/N is still special-cased due to inconsistencies with serial
43// numbers on Lumpy devices: On these devices, serial_number is identical to
44// Product_S/N with an appended checksum. Unfortunately, the sticker on the
45// packaging doesn't include that checksum either (the sticker on the device
46// does though!). The former sticker is the source of the serial number used by
47// device management service, so we prefer Product_S/N over serial number to
48// match the server.
49//
50// TODO(mnissler): Move serial_number back to the top once the server side uses
51// the correct serial number.
52const char* kMachineInfoSerialNumberKeys[] = {
53  "Product_S/N",    // Lumpy/Alex devices
54  "serial_number",  // VPD v2+ devices
55  "Product_SN",     // Mario
56  "sn",             // old ZGB devices (more recent ones use serial_number)
57};
58
59// Fetches a machine statistic value from StatisticsProvider, returns an empty
60// string on failure.
61std::string GetMachineStatistic(const std::string& key) {
62  std::string value;
63  chromeos::system::StatisticsProvider* provider =
64      chromeos::system::StatisticsProvider::GetInstance();
65  if (!provider->GetMachineStatistic(key, &value))
66    return std::string();
67
68  return value;
69}
70
71// Gets a machine flag from StatisticsProvider, returns the given
72// |default_value| if not present.
73bool GetMachineFlag(const std::string& key, bool default_value) {
74  bool value = default_value;
75  chromeos::system::StatisticsProvider* provider =
76      chromeos::system::StatisticsProvider::GetInstance();
77  if (!provider->GetMachineFlag(key, &value))
78    return default_value;
79
80  return value;
81}
82
83}  // namespace
84
85DeviceCloudPolicyManagerChromeOS::DeviceCloudPolicyManagerChromeOS(
86    scoped_ptr<DeviceCloudPolicyStoreChromeOS> store,
87    const scoped_refptr<base::SequencedTaskRunner>& task_runner,
88    const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
89    EnterpriseInstallAttributes* install_attributes)
90    : CloudPolicyManager(
91          PolicyNamespaceKey(dm_protocol::kChromeDevicePolicyType,
92                             std::string()),
93          store.get(),
94          task_runner,
95          BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE),
96          BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)),
97      device_store_(store.Pass()),
98      background_task_runner_(background_task_runner),
99      install_attributes_(install_attributes),
100      device_management_service_(NULL),
101      local_state_(NULL) {}
102
103DeviceCloudPolicyManagerChromeOS::~DeviceCloudPolicyManagerChromeOS() {}
104
105void DeviceCloudPolicyManagerChromeOS::Connect(
106    PrefService* local_state,
107    DeviceManagementService* device_management_service,
108    scoped_ptr<CloudPolicyClient::StatusProvider> device_status_provider) {
109  CHECK(!device_management_service_);
110  CHECK(device_management_service);
111  CHECK(local_state);
112
113  local_state_ = local_state;
114  device_management_service_ = device_management_service;
115  device_status_provider_ = device_status_provider.Pass();
116
117  StartIfManaged();
118}
119
120void DeviceCloudPolicyManagerChromeOS::StartEnrollment(
121    const std::string& auth_token,
122    bool is_auto_enrollment,
123    const AllowedDeviceModes& allowed_device_modes,
124    const EnrollmentCallback& callback) {
125  CHECK(device_management_service_);
126  core()->Disconnect();
127
128  enrollment_handler_.reset(
129      new EnrollmentHandlerChromeOS(
130          device_store_.get(), install_attributes_, CreateClient(),
131          background_task_runner_, auth_token,
132          install_attributes_->GetDeviceId(), is_auto_enrollment,
133          GetDeviceRequisition(), allowed_device_modes,
134          base::Bind(&DeviceCloudPolicyManagerChromeOS::EnrollmentCompleted,
135                     base::Unretained(this), callback)));
136  enrollment_handler_->StartEnrollment();
137}
138
139void DeviceCloudPolicyManagerChromeOS::CancelEnrollment() {
140  if (enrollment_handler_.get()) {
141    enrollment_handler_.reset();
142    StartIfManaged();
143  }
144}
145
146std::string DeviceCloudPolicyManagerChromeOS::GetDeviceRequisition() const {
147  std::string requisition;
148  const PrefService::Preference* pref = local_state_->FindPreference(
149      prefs::kDeviceEnrollmentRequisition);
150  if (pref->IsDefaultValue() && !chromeos::StartupUtils::IsOobeCompleted()) {
151    // OEM statistics are only loaded when OOBE is not completed.
152    requisition =
153        GetMachineStatistic(chromeos::system::kOemDeviceRequisitionKey);
154  } else {
155    pref->GetValue()->GetAsString(&requisition);
156  }
157
158  return requisition;
159}
160
161void DeviceCloudPolicyManagerChromeOS::SetDeviceRequisition(
162    const std::string& requisition) {
163  if (local_state_) {
164    if (requisition.empty()) {
165      local_state_->ClearPref(prefs::kDeviceEnrollmentRequisition);
166      local_state_->ClearPref(prefs::kDeviceEnrollmentAutoStart);
167      local_state_->ClearPref(prefs::kDeviceEnrollmentCanExit);
168    } else {
169      local_state_->SetString(prefs::kDeviceEnrollmentRequisition, requisition);
170      local_state_->SetBoolean(prefs::kDeviceEnrollmentAutoStart, true);
171      local_state_->SetBoolean(prefs::kDeviceEnrollmentCanExit, false);
172    }
173  }
174}
175
176bool DeviceCloudPolicyManagerChromeOS::ShouldAutoStartEnrollment() const {
177  if (local_state_->HasPrefPath(prefs::kDeviceEnrollmentAutoStart))
178    return local_state_->GetBoolean(prefs::kDeviceEnrollmentAutoStart);
179
180  return GetMachineFlag(chromeos::system::kOemIsEnterpriseManagedKey, false);
181}
182
183bool DeviceCloudPolicyManagerChromeOS::CanExitEnrollment() const {
184  if (local_state_->HasPrefPath(prefs::kDeviceEnrollmentCanExit))
185    return local_state_->GetBoolean(prefs::kDeviceEnrollmentCanExit);
186
187  return GetMachineFlag(chromeos::system::kOemCanExitEnterpriseEnrollmentKey,
188                        true);
189}
190
191void DeviceCloudPolicyManagerChromeOS::Shutdown() {
192  CloudPolicyManager::Shutdown();
193  device_status_provider_.reset();
194}
195
196void DeviceCloudPolicyManagerChromeOS::OnStoreLoaded(CloudPolicyStore* store) {
197  CloudPolicyManager::OnStoreLoaded(store);
198
199  if (!enrollment_handler_.get())
200    StartIfManaged();
201}
202
203// static
204void DeviceCloudPolicyManagerChromeOS::RegisterPrefs(
205    PrefRegistrySimple* registry) {
206  registry->RegisterStringPref(prefs::kDeviceEnrollmentRequisition,
207                               std::string());
208  registry->RegisterBooleanPref(prefs::kDeviceEnrollmentAutoStart, false);
209  registry->RegisterBooleanPref(prefs::kDeviceEnrollmentCanExit, true);
210}
211
212// static
213std::string DeviceCloudPolicyManagerChromeOS::GetMachineID() {
214  std::string machine_id;
215  chromeos::system::StatisticsProvider* provider =
216      chromeos::system::StatisticsProvider::GetInstance();
217  for (size_t i = 0; i < arraysize(kMachineInfoSerialNumberKeys); i++) {
218    if (provider->GetMachineStatistic(kMachineInfoSerialNumberKeys[i],
219                                      &machine_id) &&
220        !machine_id.empty()) {
221      break;
222    }
223  }
224
225  if (machine_id.empty())
226    LOG(WARNING) << "Failed to get machine id.";
227
228  return machine_id;
229}
230
231// static
232std::string DeviceCloudPolicyManagerChromeOS::GetMachineModel() {
233  return GetMachineStatistic(kMachineInfoSystemHwqual);
234}
235
236std::string DeviceCloudPolicyManagerChromeOS::GetRobotAccountId() {
237  const enterprise_management::PolicyData* policy = device_store_->policy();
238  return policy ? policy->service_account_identity() : std::string();
239}
240
241scoped_ptr<CloudPolicyClient> DeviceCloudPolicyManagerChromeOS::CreateClient() {
242  return make_scoped_ptr(
243      new CloudPolicyClient(GetMachineID(), GetMachineModel(),
244                            USER_AFFILIATION_NONE,
245                            device_status_provider_.get(),
246                            device_management_service_));
247}
248
249void DeviceCloudPolicyManagerChromeOS::EnrollmentCompleted(
250    const EnrollmentCallback& callback,
251    EnrollmentStatus status) {
252  if (status.status() == EnrollmentStatus::STATUS_SUCCESS) {
253    core()->Connect(enrollment_handler_->ReleaseClient());
254    core()->StartRefreshScheduler();
255    core()->TrackRefreshDelayPref(local_state_,
256                                  prefs::kDevicePolicyRefreshRate);
257    attestation_policy_observer_.reset(
258        new chromeos::attestation::AttestationPolicyObserver(client()));
259  } else {
260    StartIfManaged();
261  }
262
263  enrollment_handler_.reset();
264  if (!callback.is_null())
265    callback.Run(status);
266}
267
268void DeviceCloudPolicyManagerChromeOS::StartIfManaged() {
269  if (device_management_service_ &&
270      local_state_ &&
271      store()->is_initialized() &&
272      store()->is_managed() &&
273      !service()) {
274    core()->Connect(CreateClient());
275    core()->StartRefreshScheduler();
276    core()->TrackRefreshDelayPref(local_state_,
277                                  prefs::kDevicePolicyRefreshRate);
278    attestation_policy_observer_.reset(
279        new chromeos::attestation::AttestationPolicyObserver(client()));
280  }
281}
282
283}  // namespace policy
284