device_local_account_policy_service.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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_local_account_policy_service.h"
6
7#include <vector>
8
9#include "base/bind.h"
10#include "base/logging.h"
11#include "base/message_loop.h"
12#include "chrome/browser/chromeos/policy/device_local_account.h"
13#include "chrome/browser/chromeos/policy/device_local_account_policy_store.h"
14#include "chrome/browser/chromeos/settings/cros_settings.h"
15#include "chrome/browser/chromeos/settings/cros_settings_names.h"
16#include "chrome/browser/chromeos/settings/cros_settings_provider.h"
17#include "chrome/browser/chromeos/settings/device_settings_service.h"
18#include "chrome/browser/policy/cloud/cloud_policy_client.h"
19#include "chrome/browser/policy/cloud/cloud_policy_constants.h"
20#include "chrome/browser/policy/cloud/cloud_policy_refresh_scheduler.h"
21#include "chrome/browser/policy/cloud/device_management_service.h"
22#include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h"
23#include "chrome/common/chrome_notification_types.h"
24#include "chromeos/dbus/session_manager_client.h"
25#include "content/public/browser/notification_details.h"
26#include "policy/policy_constants.h"
27
28namespace em = enterprise_management;
29
30namespace policy {
31
32namespace {
33
34// Creates a broker for the device-local account with the given |user_id| and
35// |account_id|.
36scoped_ptr<DeviceLocalAccountPolicyBroker> CreateBroker(
37    const std::string& user_id,
38    const std::string& account_id,
39    chromeos::SessionManagerClient* session_manager_client,
40    chromeos::DeviceSettingsService* device_settings_service,
41    DeviceLocalAccountPolicyService* device_local_account_policy_service) {
42  scoped_ptr<DeviceLocalAccountPolicyStore> store(
43      new DeviceLocalAccountPolicyStore(account_id, session_manager_client,
44                                        device_settings_service));
45  scoped_ptr<DeviceLocalAccountPolicyBroker> broker(
46      new DeviceLocalAccountPolicyBroker(user_id, store.Pass()));
47  broker->core()->store()->AddObserver(device_local_account_policy_service);
48  broker->core()->store()->Load();
49  return broker.Pass();
50}
51
52// Creates and initializes a cloud policy client. Returns NULL if the device
53// doesn't have credentials in device settings (i.e. is not
54// enterprise-enrolled).
55scoped_ptr<CloudPolicyClient> CreateClient(
56    chromeos::DeviceSettingsService* device_settings_service,
57    DeviceManagementService* device_management_service) {
58  const em::PolicyData* policy_data = device_settings_service->policy_data();
59  if (!policy_data ||
60      !policy_data->has_request_token() ||
61      !policy_data->has_device_id() ||
62      !device_management_service) {
63    return scoped_ptr<CloudPolicyClient>();
64  }
65
66  scoped_ptr<CloudPolicyClient> client(
67      new CloudPolicyClient(std::string(), std::string(),
68                            USER_AFFILIATION_MANAGED,
69                            NULL, device_management_service));
70  client->SetupRegistration(policy_data->request_token(),
71                            policy_data->device_id());
72  return client.Pass();
73}
74
75}  // namespace
76
77DeviceLocalAccountPolicyBroker::DeviceLocalAccountPolicyBroker(
78    const std::string& user_id,
79    scoped_ptr<DeviceLocalAccountPolicyStore> store)
80    : user_id_(user_id),
81      store_(store.Pass()),
82      core_(PolicyNamespaceKey(dm_protocol::kChromePublicAccountPolicyType,
83                               store_->account_id()),
84            store_.get()) {}
85
86DeviceLocalAccountPolicyBroker::~DeviceLocalAccountPolicyBroker() {}
87
88void DeviceLocalAccountPolicyBroker::Connect(
89    scoped_ptr<CloudPolicyClient> client) {
90  core_.Connect(client.Pass());
91  core_.StartRefreshScheduler();
92  UpdateRefreshDelay();
93}
94
95void DeviceLocalAccountPolicyBroker::Disconnect() {
96  core_.Disconnect();
97}
98
99void DeviceLocalAccountPolicyBroker::UpdateRefreshDelay() {
100  if (core_.refresh_scheduler()) {
101    const Value* policy_value =
102        store_->policy_map().GetValue(key::kPolicyRefreshRate);
103    int delay = 0;
104    if (policy_value && policy_value->GetAsInteger(&delay))
105      core_.refresh_scheduler()->SetRefreshDelay(delay);
106  }
107}
108
109std::string DeviceLocalAccountPolicyBroker::GetDisplayName() const {
110  std::string display_name;
111  const base::Value* display_name_value =
112      store_->policy_map().GetValue(policy::key::kUserDisplayName);
113  if (display_name_value)
114    display_name_value->GetAsString(&display_name);
115  return display_name;
116}
117
118DeviceLocalAccountPolicyService::PolicyBrokerWrapper::PolicyBrokerWrapper()
119    : parent(NULL), broker(NULL) {}
120
121DeviceLocalAccountPolicyBroker*
122    DeviceLocalAccountPolicyService::PolicyBrokerWrapper::GetBroker() {
123  if (!broker) {
124    broker = CreateBroker(user_id, account_id,
125                          parent->session_manager_client_,
126                          parent->device_settings_service_,
127                          parent).release();
128  }
129  return broker;
130}
131
132void DeviceLocalAccountPolicyService::PolicyBrokerWrapper::ConnectIfPossible() {
133  if (broker && broker->core()->client())
134    return;
135  scoped_ptr<CloudPolicyClient> client(CreateClient(
136      parent->device_settings_service_,
137      parent->device_management_service_));
138  if (client)
139    GetBroker()->Connect(client.Pass());
140}
141
142void DeviceLocalAccountPolicyService::PolicyBrokerWrapper::Disconnect() {
143  if (broker)
144    broker->Disconnect();
145}
146
147void DeviceLocalAccountPolicyService::PolicyBrokerWrapper::DeleteBroker() {
148  if (!broker)
149    return;
150  broker->core()->store()->RemoveObserver(parent);
151  delete broker;
152  broker = NULL;
153}
154
155DeviceLocalAccountPolicyService::DeviceLocalAccountPolicyService(
156    chromeos::SessionManagerClient* session_manager_client,
157    chromeos::DeviceSettingsService* device_settings_service,
158    chromeos::CrosSettings* cros_settings)
159    : session_manager_client_(session_manager_client),
160      device_settings_service_(device_settings_service),
161      cros_settings_(cros_settings),
162      device_management_service_(NULL),
163      cros_settings_callback_factory_(this) {
164  cros_settings_->AddSettingsObserver(
165      chromeos::kAccountsPrefDeviceLocalAccounts, this);
166  UpdateAccountList();
167}
168
169DeviceLocalAccountPolicyService::~DeviceLocalAccountPolicyService() {
170  cros_settings_->RemoveSettingsObserver(
171      chromeos::kAccountsPrefDeviceLocalAccounts, this);
172  DeleteBrokers(&policy_brokers_);
173}
174
175void DeviceLocalAccountPolicyService::Connect(
176    DeviceManagementService* device_management_service) {
177  DCHECK(!device_management_service_);
178  device_management_service_ = device_management_service;
179
180  // Connect the brokers.
181  for (PolicyBrokerMap::iterator it(policy_brokers_.begin());
182       it != policy_brokers_.end(); ++it) {
183    it->second.ConnectIfPossible();
184  }
185}
186
187void DeviceLocalAccountPolicyService::Disconnect() {
188  DCHECK(device_management_service_);
189  device_management_service_ = NULL;
190
191  // Disconnect the brokers.
192  for (PolicyBrokerMap::iterator it(policy_brokers_.begin());
193       it != policy_brokers_.end(); ++it) {
194    it->second.Disconnect();
195  }
196}
197
198DeviceLocalAccountPolicyBroker*
199    DeviceLocalAccountPolicyService::GetBrokerForUser(
200        const std::string& user_id) {
201  PolicyBrokerMap::iterator entry = policy_brokers_.find(user_id);
202  if (entry == policy_brokers_.end())
203    return NULL;
204
205  return entry->second.GetBroker();
206}
207
208bool DeviceLocalAccountPolicyService::IsPolicyAvailableForUser(
209    const std::string& user_id) {
210  DeviceLocalAccountPolicyBroker* broker = GetBrokerForUser(user_id);
211  return broker && broker->core()->store()->is_managed();
212}
213
214void DeviceLocalAccountPolicyService::AddObserver(Observer* observer) {
215  observers_.AddObserver(observer);
216}
217
218void DeviceLocalAccountPolicyService::RemoveObserver(Observer* observer) {
219  observers_.RemoveObserver(observer);
220}
221
222void DeviceLocalAccountPolicyService::Observe(
223    int type,
224    const content::NotificationSource& source,
225    const content::NotificationDetails& details) {
226  if (type != chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED ||
227      *content::Details<const std::string>(details).ptr() !=
228          chromeos::kAccountsPrefDeviceLocalAccounts) {
229    NOTREACHED();
230    return;
231  }
232
233  // Avoid unnecessary calls to UpdateAccountList(): If an earlier call is still
234  // pending (because the |cros_settings_| are not trusted yet), the updated
235  // account list will be processed by that call when it eventually runs.
236  if (!cros_settings_callback_factory_.HasWeakPtrs())
237    UpdateAccountList();
238}
239
240void DeviceLocalAccountPolicyService::OnStoreLoaded(CloudPolicyStore* store) {
241  DeviceLocalAccountPolicyBroker* broker = GetBrokerForStore(store);
242  DCHECK(broker);
243  if (!broker)
244    return;
245  broker->UpdateRefreshDelay();
246  FOR_EACH_OBSERVER(Observer, observers_, OnPolicyUpdated(broker->user_id()));
247}
248
249void DeviceLocalAccountPolicyService::OnStoreError(CloudPolicyStore* store) {
250  DeviceLocalAccountPolicyBroker* broker = GetBrokerForStore(store);
251  DCHECK(broker);
252  if (!broker)
253    return;
254  FOR_EACH_OBSERVER(Observer, observers_, OnPolicyUpdated(broker->user_id()));
255}
256
257void DeviceLocalAccountPolicyService::UpdateAccountList() {
258  if (chromeos::CrosSettingsProvider::TRUSTED !=
259          cros_settings_->PrepareTrustedValues(
260              base::Bind(&DeviceLocalAccountPolicyService::UpdateAccountList,
261                         cros_settings_callback_factory_.GetWeakPtr()))) {
262    return;
263  }
264
265  // Update |policy_brokers_|, keeping existing entries.
266  PolicyBrokerMap new_policy_brokers;
267  const std::vector<DeviceLocalAccount> device_local_accounts =
268      GetDeviceLocalAccounts(cros_settings_);
269  for (std::vector<DeviceLocalAccount>::const_iterator it =
270           device_local_accounts.begin();
271       it != device_local_accounts.end(); ++it) {
272    PolicyBrokerWrapper& wrapper = new_policy_brokers[it->user_id];
273    wrapper.user_id = it->user_id;
274    wrapper.account_id = it->account_id;
275    wrapper.parent = this;
276
277    // Reuse the existing broker if present.
278    PolicyBrokerWrapper& existing_wrapper = policy_brokers_[it->user_id];
279    wrapper.broker = existing_wrapper.broker;
280    existing_wrapper.broker = NULL;
281
282    // Fire up the cloud connection for fetching policy for the account from
283    // the cloud if this is an enterprise-managed device.
284    wrapper.ConnectIfPossible();
285  }
286  policy_brokers_.swap(new_policy_brokers);
287  DeleteBrokers(&new_policy_brokers);
288
289  FOR_EACH_OBSERVER(Observer, observers_, OnDeviceLocalAccountsChanged());
290}
291
292void DeviceLocalAccountPolicyService::DeleteBrokers(PolicyBrokerMap* map) {
293  for (PolicyBrokerMap::iterator it = map->begin(); it != map->end(); ++it)
294    it->second.DeleteBroker();
295  map->clear();
296}
297
298DeviceLocalAccountPolicyBroker*
299    DeviceLocalAccountPolicyService::GetBrokerForStore(
300        CloudPolicyStore* store) {
301  for (PolicyBrokerMap::iterator it(policy_brokers_.begin());
302       it != policy_brokers_.end(); ++it) {
303    if (it->second.broker && it->second.broker->core()->store() == store)
304      return it->second.broker;
305  }
306  return NULL;
307}
308
309}  // namespace policy
310