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