device_settings_service.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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/settings/device_settings_service.h" 6 7#include "base/bind.h" 8#include "base/logging.h" 9#include "base/message_loop/message_loop.h" 10#include "base/stl_util.h" 11#include "base/time/time.h" 12#include "chrome/browser/chrome_notification_types.h" 13#include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h" 14#include "chrome/browser/chromeos/settings/owner_key_util.h" 15#include "chrome/browser/chromeos/settings/session_manager_operation.h" 16#include "components/policy/core/common/cloud/cloud_policy_constants.h" 17#include "content/public/browser/browser_thread.h" 18#include "content/public/browser/notification_service.h" 19#include "content/public/browser/notification_source.h" 20#include "crypto/rsa_private_key.h" 21 22namespace em = enterprise_management; 23 24namespace { 25 26// Delay between load retries when there was a validation error. 27// NOTE: This code is here to mitigate clock loss on some devices where policy 28// loads will fail with a validation error caused by RTC clock being reset when 29// the battery is drained. 30int kLoadRetryDelayMs = 1000 * 5; 31// Maximal number of retries before we give up. Calculated to allow for 10 min 32// of retry time. 33int kMaxLoadRetries = (1000 * 60 * 10) / kLoadRetryDelayMs; 34 35} // namespace 36 37namespace chromeos { 38 39DeviceSettingsService::Observer::~Observer() {} 40 41static DeviceSettingsService* g_device_settings_service = NULL; 42 43// static 44void DeviceSettingsService::Initialize() { 45 CHECK(!g_device_settings_service); 46 g_device_settings_service = new DeviceSettingsService(); 47} 48 49// static 50bool DeviceSettingsService::IsInitialized() { 51 return g_device_settings_service; 52} 53 54// static 55void DeviceSettingsService::Shutdown() { 56 DCHECK(g_device_settings_service); 57 delete g_device_settings_service; 58 g_device_settings_service = NULL; 59} 60 61// static 62DeviceSettingsService* DeviceSettingsService::Get() { 63 CHECK(g_device_settings_service); 64 return g_device_settings_service; 65} 66 67DeviceSettingsService::DeviceSettingsService() 68 : session_manager_client_(NULL), 69 store_status_(STORE_SUCCESS), 70 load_retries_left_(kMaxLoadRetries), 71 weak_factory_(this) { 72} 73 74DeviceSettingsService::~DeviceSettingsService() { 75 DCHECK(pending_operations_.empty()); 76} 77 78void DeviceSettingsService::SetSessionManager( 79 SessionManagerClient* session_manager_client, 80 scoped_refptr<OwnerKeyUtil> owner_key_util) { 81 DCHECK(session_manager_client); 82 DCHECK(owner_key_util.get()); 83 DCHECK(!session_manager_client_); 84 DCHECK(!owner_key_util_.get()); 85 86 session_manager_client_ = session_manager_client; 87 owner_key_util_ = owner_key_util; 88 89 session_manager_client_->AddObserver(this); 90 91 StartNextOperation(); 92} 93 94void DeviceSettingsService::UnsetSessionManager() { 95 STLDeleteContainerPointers(pending_operations_.begin(), 96 pending_operations_.end()); 97 pending_operations_.clear(); 98 99 if (session_manager_client_) 100 session_manager_client_->RemoveObserver(this); 101 session_manager_client_ = NULL; 102 owner_key_util_ = NULL; 103} 104 105scoped_refptr<PublicKey> DeviceSettingsService::GetPublicKey() { 106 return public_key_; 107} 108 109void DeviceSettingsService::Load() { 110 EnqueueLoad(false); 111} 112 113void DeviceSettingsService::SignAndStore( 114 scoped_ptr<em::ChromeDeviceSettingsProto> new_settings, 115 const base::Closure& callback) { 116 if (!delegate_) 117 HandleError(STORE_KEY_UNAVAILABLE, callback); 118 else 119 delegate_->SignAndStoreAsync(new_settings.Pass(), callback); 120} 121 122void DeviceSettingsService::SetManagementSettings( 123 em::PolicyData::ManagementMode management_mode, 124 const std::string& request_token, 125 const std::string& device_id, 126 const base::Closure& callback) { 127 if (!delegate_) { 128 HandleError(STORE_KEY_UNAVAILABLE, callback); 129 } else { 130 delegate_->SetManagementSettingsAsync( 131 management_mode, request_token, device_id, callback); 132 } 133} 134 135void DeviceSettingsService::Store(scoped_ptr<em::PolicyFetchResponse> policy, 136 const base::Closure& callback) { 137 Enqueue( 138 new StoreSettingsOperation( 139 base::Bind(&DeviceSettingsService::HandleCompletedOperation, 140 weak_factory_.GetWeakPtr(), 141 callback), 142 policy.Pass())); 143} 144 145DeviceSettingsService::OwnershipStatus 146 DeviceSettingsService::GetOwnershipStatus() { 147 if (public_key_) 148 return public_key_->is_loaded() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE; 149 return OWNERSHIP_UNKNOWN; 150} 151 152void DeviceSettingsService::GetOwnershipStatusAsync( 153 const OwnershipStatusCallback& callback) { 154 if (public_key_) { 155 // If there is a key, report status immediately. 156 base::MessageLoop::current()->PostTask( 157 FROM_HERE, base::Bind(callback, GetOwnershipStatus())); 158 } else { 159 // If the key hasn't been loaded yet, enqueue the callback to be fired when 160 // the next SessionManagerOperation completes. If no operation is pending, 161 // start a load operation to fetch the key and report the result. 162 pending_ownership_status_callbacks_.push_back(callback); 163 if (pending_operations_.empty()) 164 EnqueueLoad(false); 165 } 166} 167 168bool DeviceSettingsService::HasPrivateOwnerKey() { 169 return delegate_ && delegate_->IsOwner(); 170} 171 172void DeviceSettingsService::InitOwner( 173 const std::string& username, 174 const base::WeakPtr<PrivateKeyDelegate>& delegate) { 175 // When InitOwner() is called twice with the same |username| it's 176 // worth to reload settings since owner key may become available. 177 if (!username_.empty() && username_ != username) 178 return; 179 username_ = username; 180 delegate_ = delegate; 181 182 EnsureReload(true); 183} 184 185const std::string& DeviceSettingsService::GetUsername() const { 186 return username_; 187} 188 189void DeviceSettingsService::AddObserver(Observer* observer) { 190 observers_.AddObserver(observer); 191} 192 193void DeviceSettingsService::RemoveObserver(Observer* observer) { 194 observers_.RemoveObserver(observer); 195} 196 197void DeviceSettingsService::OwnerKeySet(bool success) { 198 if (!success) { 199 LOG(ERROR) << "Owner key change failed."; 200 return; 201 } 202 203 public_key_ = NULL; 204 EnsureReload(true); 205} 206 207void DeviceSettingsService::PropertyChangeComplete(bool success) { 208 if (!success) { 209 LOG(ERROR) << "Policy update failed."; 210 return; 211 } 212 213 EnsureReload(false); 214} 215 216void DeviceSettingsService::Enqueue(SessionManagerOperation* operation) { 217 pending_operations_.push_back(operation); 218 if (pending_operations_.front() == operation) 219 StartNextOperation(); 220} 221 222void DeviceSettingsService::EnqueueLoad(bool force_key_load) { 223 SessionManagerOperation* operation = 224 new LoadSettingsOperation( 225 base::Bind(&DeviceSettingsService::HandleCompletedOperation, 226 weak_factory_.GetWeakPtr(), 227 base::Closure())); 228 operation->set_force_key_load(force_key_load); 229 operation->set_username(username_); 230 operation->set_delegate(delegate_); 231 Enqueue(operation); 232} 233 234void DeviceSettingsService::EnsureReload(bool force_key_load) { 235 if (!pending_operations_.empty()) { 236 pending_operations_.front()->set_username(username_); 237 pending_operations_.front()->set_delegate(delegate_); 238 pending_operations_.front()->RestartLoad(force_key_load); 239 } else { 240 EnqueueLoad(force_key_load); 241 } 242} 243 244void DeviceSettingsService::StartNextOperation() { 245 if (!pending_operations_.empty() && 246 session_manager_client_ && 247 owner_key_util_.get()) { 248 pending_operations_.front()->Start( 249 session_manager_client_, owner_key_util_, public_key_); 250 } 251} 252 253void DeviceSettingsService::HandleCompletedOperation( 254 const base::Closure& callback, 255 SessionManagerOperation* operation, 256 Status status) { 257 DCHECK_EQ(operation, pending_operations_.front()); 258 store_status_ = status; 259 260 OwnershipStatus ownership_status = OWNERSHIP_UNKNOWN; 261 scoped_refptr<PublicKey> new_key(operation->public_key()); 262 if (new_key.get()) { 263 ownership_status = new_key->is_loaded() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE; 264 } else { 265 NOTREACHED() << "Failed to determine key status."; 266 } 267 268 bool new_owner_key = false; 269 if (public_key_.get() != new_key.get()) { 270 public_key_ = new_key; 271 new_owner_key = true; 272 } 273 274 if (status == STORE_SUCCESS) { 275 policy_data_ = operation->policy_data().Pass(); 276 device_settings_ = operation->device_settings().Pass(); 277 load_retries_left_ = kMaxLoadRetries; 278 } else if (status != STORE_KEY_UNAVAILABLE) { 279 LOG(ERROR) << "Session manager operation failed: " << status; 280 // Validation errors can be temporary if the rtc has gone on holiday for a 281 // short while. So we will retry such loads for up to 10 minutes. 282 if (status == STORE_TEMP_VALIDATION_ERROR) { 283 if (load_retries_left_ > 0) { 284 load_retries_left_--; 285 LOG(ERROR) << "A re-load has been scheduled due to a validation error."; 286 content::BrowserThread::PostDelayedTask( 287 content::BrowserThread::UI, 288 FROM_HERE, 289 base::Bind(&DeviceSettingsService::Load, base::Unretained(this)), 290 base::TimeDelta::FromMilliseconds(kLoadRetryDelayMs)); 291 } else { 292 // Once we've given up retrying, the validation error is not temporary 293 // anymore. 294 store_status_ = STORE_VALIDATION_ERROR; 295 } 296 } 297 } 298 299 if (new_owner_key) { 300 FOR_EACH_OBSERVER(Observer, observers_, OwnershipStatusChanged()); 301 content::NotificationService::current()->Notify( 302 chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED, 303 content::Source<DeviceSettingsService>(this), 304 content::NotificationService::NoDetails()); 305 } 306 307 FOR_EACH_OBSERVER(Observer, observers_, DeviceSettingsUpdated()); 308 309 std::vector<OwnershipStatusCallback> callbacks; 310 callbacks.swap(pending_ownership_status_callbacks_); 311 for (std::vector<OwnershipStatusCallback>::iterator iter(callbacks.begin()); 312 iter != callbacks.end(); ++iter) { 313 iter->Run(ownership_status); 314 } 315 316 // The completion callback happens after the notification so clients can 317 // filter self-triggered updates. 318 if (!callback.is_null()) 319 callback.Run(); 320 321 // Only remove the pending operation here, so new operations triggered by any 322 // of the callbacks above are queued up properly. 323 pending_operations_.pop_front(); 324 delete operation; 325 326 StartNextOperation(); 327} 328 329void DeviceSettingsService::HandleError(Status status, 330 const base::Closure& callback) { 331 store_status_ = status; 332 333 LOG(ERROR) << "Session manager operation failed: " << status; 334 335 FOR_EACH_OBSERVER(Observer, observers_, DeviceSettingsUpdated()); 336 337 // The completion callback happens after the notification so clients can 338 // filter self-triggered updates. 339 if (!callback.is_null()) 340 callback.Run(); 341} 342 343void DeviceSettingsService::OnSignAndStoreOperationCompleted(Status status) { 344 store_status_ = status; 345 FOR_EACH_OBSERVER(Observer, observers_, DeviceSettingsUpdated()); 346} 347 348ScopedTestDeviceSettingsService::ScopedTestDeviceSettingsService() { 349 DeviceSettingsService::Initialize(); 350} 351 352ScopedTestDeviceSettingsService::~ScopedTestDeviceSettingsService() { 353 // Clean pending operations. 354 DeviceSettingsService::Get()->UnsetSessionManager(); 355 DeviceSettingsService::Shutdown(); 356} 357 358} // namespace chromeos 359