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