device_local_account_policy_service.cc revision b2df76ea8fec9e32f6f3718986dba0d95315b29c
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 "base/logging.h"
8#include "base/message_loop.h"
9#include "chrome/browser/chromeos/policy/device_local_account_policy_store.h"
10#include "chrome/browser/policy/cloud/cloud_policy_client.h"
11#include "chrome/browser/policy/cloud/cloud_policy_constants.h"
12#include "chrome/browser/policy/cloud/cloud_policy_refresh_scheduler.h"
13#include "chrome/browser/policy/cloud/device_management_service.h"
14#include "chrome/browser/policy/proto/chromeos/chrome_device_policy.pb.h"
15#include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h"
16#include "chromeos/dbus/session_manager_client.h"
17#include "policy/policy_constants.h"
18
19namespace em = enterprise_management;
20
21namespace policy {
22
23DeviceLocalAccountPolicyBroker::DeviceLocalAccountPolicyBroker(
24    scoped_ptr<DeviceLocalAccountPolicyStore> store)
25    : store_(store.Pass()),
26      core_(PolicyNamespaceKey(dm_protocol::kChromePublicAccountPolicyType,
27                               store_->account_id()),
28            store_.get()) {}
29
30DeviceLocalAccountPolicyBroker::~DeviceLocalAccountPolicyBroker() {}
31
32const std::string& DeviceLocalAccountPolicyBroker::account_id() const {
33  return store_->account_id();
34}
35
36void DeviceLocalAccountPolicyBroker::Connect(
37    scoped_ptr<CloudPolicyClient> client) {
38  core_.Connect(client.Pass());
39  core_.StartRefreshScheduler();
40  UpdateRefreshDelay();
41}
42
43void DeviceLocalAccountPolicyBroker::Disconnect() {
44  core_.Disconnect();
45}
46
47void DeviceLocalAccountPolicyBroker::UpdateRefreshDelay() {
48  if (core_.refresh_scheduler()) {
49    const Value* policy_value =
50        store_->policy_map().GetValue(key::kPolicyRefreshRate);
51    int delay = 0;
52    if (policy_value && policy_value->GetAsInteger(&delay))
53      core_.refresh_scheduler()->SetRefreshDelay(delay);
54  }
55}
56
57std::string DeviceLocalAccountPolicyBroker::GetDisplayName() const {
58  std::string display_name;
59  const base::Value* display_name_value =
60      store_->policy_map().GetValue(policy::key::kUserDisplayName);
61  if (display_name_value)
62    display_name_value->GetAsString(&display_name);
63  return display_name;
64}
65
66DeviceLocalAccountPolicyService::DeviceLocalAccountPolicyService(
67    chromeos::SessionManagerClient* session_manager_client,
68    chromeos::DeviceSettingsService* device_settings_service)
69    : session_manager_client_(session_manager_client),
70      device_settings_service_(device_settings_service),
71      device_management_service_(NULL) {
72  device_settings_service_->AddObserver(this);
73  DeviceSettingsUpdated();
74}
75
76DeviceLocalAccountPolicyService::~DeviceLocalAccountPolicyService() {
77  device_settings_service_->RemoveObserver(this);
78  DeleteBrokers(&policy_brokers_);
79}
80
81void DeviceLocalAccountPolicyService::Connect(
82    DeviceManagementService* device_management_service) {
83  DCHECK(!device_management_service_);
84  device_management_service_ = device_management_service;
85
86  // Connect the brokers.
87  for (PolicyBrokerMap::iterator broker(policy_brokers_.begin());
88       broker != policy_brokers_.end(); ++broker) {
89    DCHECK(!broker->second->core()->client());
90    broker->second->Connect(
91        CreateClientForAccount(broker->second->account_id()).Pass());
92  }
93}
94
95void DeviceLocalAccountPolicyService::Disconnect() {
96  DCHECK(device_management_service_);
97  device_management_service_ = NULL;
98
99  // Disconnect the brokers.
100  for (PolicyBrokerMap::iterator broker(policy_brokers_.begin());
101       broker != policy_brokers_.end(); ++broker) {
102    broker->second->Disconnect();
103  }
104}
105
106DeviceLocalAccountPolicyBroker*
107    DeviceLocalAccountPolicyService::GetBrokerForAccount(
108        const std::string& account_id) {
109  PolicyBrokerMap::iterator entry = policy_brokers_.find(account_id);
110  if (entry == policy_brokers_.end())
111    return NULL;
112
113  if (!entry->second)
114    entry->second = CreateBroker(account_id).release();
115
116  return entry->second;
117}
118
119bool DeviceLocalAccountPolicyService::IsPolicyAvailableForAccount(
120    const std::string& account_id) {
121  DeviceLocalAccountPolicyBroker* broker = GetBrokerForAccount(account_id);
122  return broker && broker->core()->store()->is_managed();
123}
124
125void DeviceLocalAccountPolicyService::AddObserver(Observer* observer) {
126  observers_.AddObserver(observer);
127}
128
129void DeviceLocalAccountPolicyService::RemoveObserver(Observer* observer) {
130  observers_.RemoveObserver(observer);
131}
132
133void DeviceLocalAccountPolicyService::OwnershipStatusChanged() {
134  // TODO(mnissler): The policy key has changed, re-fetch policy. For
135  // consumer devices, re-sign the current settings and send updates to
136  // session_manager.
137}
138
139void DeviceLocalAccountPolicyService::DeviceSettingsUpdated() {
140  const em::ChromeDeviceSettingsProto* device_settings =
141      device_settings_service_->device_settings();
142  if (device_settings)
143    UpdateAccountList(*device_settings);
144}
145
146void DeviceLocalAccountPolicyService::OnStoreLoaded(CloudPolicyStore* store) {
147  DeviceLocalAccountPolicyBroker* broker = GetBrokerForStore(store);
148  broker->UpdateRefreshDelay();
149  FOR_EACH_OBSERVER(Observer, observers_,
150                    OnPolicyUpdated(broker->account_id()));
151}
152
153void DeviceLocalAccountPolicyService::OnStoreError(CloudPolicyStore* store) {
154  DeviceLocalAccountPolicyBroker* broker = GetBrokerForStore(store);
155  FOR_EACH_OBSERVER(Observer, observers_,
156                    OnPolicyUpdated(broker->account_id()));
157}
158
159void DeviceLocalAccountPolicyService::UpdateAccountList(
160    const em::ChromeDeviceSettingsProto& device_settings) {
161  using google::protobuf::RepeatedPtrField;
162
163  // Update |policy_brokers_|, keeping existing entries.
164  PolicyBrokerMap new_policy_brokers;
165  const RepeatedPtrField<em::DeviceLocalAccountInfoProto>& accounts =
166      device_settings.device_local_accounts().account();
167  RepeatedPtrField<em::DeviceLocalAccountInfoProto>::const_iterator entry;
168  for (entry = accounts.begin(); entry != accounts.end(); ++entry) {
169    std::string account_id;
170    if (entry->has_type() &&
171        entry->type() ==
172            em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION) {
173      account_id = entry->account_id();
174    } else if (entry->has_deprecated_public_session_id()) {
175      account_id = entry->deprecated_public_session_id();
176    }
177
178    if (account_id.empty())
179      continue;
180
181    // Sanity check for whether this account ID has already been processed.
182    DeviceLocalAccountPolicyBroker*& new_broker =
183        new_policy_brokers[account_id];
184    if (new_broker) {
185      LOG(WARNING) << "Duplicate public account " << account_id;
186      continue;
187    }
188
189    // Reuse the existing broker if present.
190    DeviceLocalAccountPolicyBroker*& existing_broker =
191        policy_brokers_[account_id];
192    new_broker = existing_broker;
193    existing_broker = NULL;
194
195    // Fire up the cloud connection for fetching policy for the account from
196    // the cloud if this is an enterprise-managed device.
197    if (!new_broker || !new_broker->core()->client()) {
198      scoped_ptr<CloudPolicyClient> client(
199          CreateClientForAccount(account_id));
200      if (client.get()) {
201        if (!new_broker)
202          new_broker = CreateBroker(account_id).release();
203        new_broker->Connect(client.Pass());
204      }
205    }
206  }
207  policy_brokers_.swap(new_policy_brokers);
208  DeleteBrokers(&new_policy_brokers);
209
210  FOR_EACH_OBSERVER(Observer, observers_, OnDeviceLocalAccountsChanged());
211}
212
213scoped_ptr<DeviceLocalAccountPolicyBroker>
214    DeviceLocalAccountPolicyService::CreateBroker(
215        const std::string& account_id) {
216  scoped_ptr<DeviceLocalAccountPolicyStore> store(
217      new DeviceLocalAccountPolicyStore(account_id, session_manager_client_,
218                                        device_settings_service_));
219  scoped_ptr<DeviceLocalAccountPolicyBroker> broker(
220      new DeviceLocalAccountPolicyBroker(store.Pass()));
221  broker->core()->store()->AddObserver(this);
222  broker->core()->store()->Load();
223  return broker.Pass();
224}
225
226void DeviceLocalAccountPolicyService::DeleteBrokers(PolicyBrokerMap* map) {
227  for (PolicyBrokerMap::iterator broker = map->begin(); broker != map->end();
228       ++broker) {
229    if (broker->second) {
230      broker->second->core()->store()->RemoveObserver(this);
231      delete broker->second;
232    }
233  }
234  map->clear();
235}
236
237DeviceLocalAccountPolicyBroker*
238    DeviceLocalAccountPolicyService::GetBrokerForStore(
239        CloudPolicyStore* store) {
240  for (PolicyBrokerMap::iterator broker(policy_brokers_.begin());
241       broker != policy_brokers_.end(); ++broker) {
242    if (broker->second->core()->store() == store)
243      return broker->second;
244  }
245  return NULL;
246}
247
248scoped_ptr<CloudPolicyClient>
249    DeviceLocalAccountPolicyService::CreateClientForAccount(
250        const std::string& account_id) {
251  const em::PolicyData* policy_data = device_settings_service_->policy_data();
252  if (!policy_data ||
253      !policy_data->has_request_token() ||
254      !policy_data->has_device_id() ||
255      !device_management_service_) {
256    return scoped_ptr<CloudPolicyClient>();
257  }
258
259  scoped_ptr<CloudPolicyClient> client(
260      new CloudPolicyClient(std::string(), std::string(),
261                            USER_AFFILIATION_MANAGED,
262                            NULL, device_management_service_));
263  client->SetupRegistration(policy_data->request_token(),
264                            policy_data->device_id());
265  return client.Pass();
266}
267
268}  // namespace policy
269