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