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