Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/chromeos/settings/device_settings_service.h" | 5 #include "chrome/browser/chromeos/settings/device_settings_service.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/location.h" | 10 #include "base/location.h" |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 72 g_device_settings_service = NULL; | 72 g_device_settings_service = NULL; |
| 73 } | 73 } |
| 74 | 74 |
| 75 // static | 75 // static |
| 76 DeviceSettingsService* DeviceSettingsService::Get() { | 76 DeviceSettingsService* DeviceSettingsService::Get() { |
| 77 CHECK(g_device_settings_service); | 77 CHECK(g_device_settings_service); |
| 78 return g_device_settings_service; | 78 return g_device_settings_service; |
| 79 } | 79 } |
| 80 | 80 |
| 81 DeviceSettingsService::DeviceSettingsService() | 81 DeviceSettingsService::DeviceSettingsService() |
| 82 : session_manager_client_(NULL), | 82 : load_retries_left_(kMaxLoadRetries), weak_factory_(this) {} |
| 83 store_status_(STORE_SUCCESS), | |
| 84 load_retries_left_(kMaxLoadRetries), | |
| 85 weak_factory_(this) { | |
| 86 } | |
| 87 | 83 |
| 88 DeviceSettingsService::~DeviceSettingsService() { | 84 DeviceSettingsService::~DeviceSettingsService() { |
| 89 DCHECK(pending_operations_.empty()); | 85 DCHECK(pending_operations_.empty()); |
| 90 for (auto& observer : observers_) | 86 for (auto& observer : observers_) |
| 91 observer.OnDeviceSettingsServiceShutdown(); | 87 observer.OnDeviceSettingsServiceShutdown(); |
| 92 } | 88 } |
| 93 | 89 |
| 94 void DeviceSettingsService::SetSessionManager( | 90 void DeviceSettingsService::SetSessionManager( |
| 95 SessionManagerClient* session_manager_client, | 91 SessionManagerClient* session_manager_client, |
| 96 scoped_refptr<OwnerKeyUtil> owner_key_util) { | 92 scoped_refptr<OwnerKeyUtil> owner_key_util) { |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 109 | 105 |
| 110 void DeviceSettingsService::UnsetSessionManager() { | 106 void DeviceSettingsService::UnsetSessionManager() { |
| 111 pending_operations_.clear(); | 107 pending_operations_.clear(); |
| 112 | 108 |
| 113 if (session_manager_client_) | 109 if (session_manager_client_) |
| 114 session_manager_client_->RemoveObserver(this); | 110 session_manager_client_->RemoveObserver(this); |
| 115 session_manager_client_ = NULL; | 111 session_manager_client_ = NULL; |
| 116 owner_key_util_ = NULL; | 112 owner_key_util_ = NULL; |
| 117 } | 113 } |
| 118 | 114 |
| 115 void DeviceSettingsService::SetDeviceMode(policy::DeviceMode device_mode) { | |
| 116 // Device mode can only change once. | |
| 117 DCHECK_EQ(policy::DEVICE_MODE_PENDING, device_mode_); | |
| 118 device_mode_ = device_mode; | |
| 119 if (GetOwnershipStatus() != OWNERSHIP_UNKNOWN) { | |
| 120 RunPendingOwnershipStatusCallbacks(); | |
| 121 } | |
| 122 } | |
| 123 | |
| 119 scoped_refptr<PublicKey> DeviceSettingsService::GetPublicKey() { | 124 scoped_refptr<PublicKey> DeviceSettingsService::GetPublicKey() { |
| 120 return public_key_; | 125 return public_key_; |
| 121 } | 126 } |
| 122 | 127 |
| 123 void DeviceSettingsService::Load() { | 128 void DeviceSettingsService::Load() { |
| 124 EnqueueLoad(false); | 129 EnqueueLoad(false); |
| 125 } | 130 } |
| 126 | 131 |
| 127 void DeviceSettingsService::Store( | 132 void DeviceSettingsService::Store( |
| 128 std::unique_ptr<em::PolicyFetchResponse> policy, | 133 std::unique_ptr<em::PolicyFetchResponse> policy, |
| 129 const base::Closure& callback) { | 134 const base::Closure& callback) { |
| 130 Enqueue(linked_ptr<SessionManagerOperation>(new StoreSettingsOperation( | 135 Enqueue(linked_ptr<SessionManagerOperation>(new StoreSettingsOperation( |
| 131 base::Bind(&DeviceSettingsService::HandleCompletedOperation, | 136 base::Bind(&DeviceSettingsService::HandleCompletedOperation, |
| 132 weak_factory_.GetWeakPtr(), callback), | 137 weak_factory_.GetWeakPtr(), callback), |
| 133 std::move(policy)))); | 138 std::move(policy)))); |
| 134 } | 139 } |
| 135 | 140 |
| 136 DeviceSettingsService::OwnershipStatus | 141 DeviceSettingsService::OwnershipStatus |
| 137 DeviceSettingsService::GetOwnershipStatus() { | 142 DeviceSettingsService::GetOwnershipStatus() { |
| 138 if (public_key_.get()) | 143 if (public_key_.get()) |
| 139 return public_key_->is_loaded() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE; | 144 return public_key_->is_loaded() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE; |
| 145 if (device_mode_ == policy::DEVICE_MODE_ENTERPRISE_AD) | |
| 146 return OWNERSHIP_TAKEN; | |
| 140 return OWNERSHIP_UNKNOWN; | 147 return OWNERSHIP_UNKNOWN; |
| 141 } | 148 } |
| 142 | 149 |
| 143 void DeviceSettingsService::GetOwnershipStatusAsync( | 150 void DeviceSettingsService::GetOwnershipStatusAsync( |
| 144 const OwnershipStatusCallback& callback) { | 151 const OwnershipStatusCallback& callback) { |
| 145 if (public_key_.get()) { | 152 if (GetOwnershipStatus() != OWNERSHIP_UNKNOWN) { |
| 146 // If there is a key, report status immediately. | 153 // Report status immediately. |
| 147 base::ThreadTaskRunnerHandle::Get()->PostTask( | 154 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 148 FROM_HERE, base::Bind(callback, GetOwnershipStatus())); | 155 FROM_HERE, base::Bind(callback, GetOwnershipStatus())); |
| 149 } else { | 156 } else { |
| 150 // If the key hasn't been loaded yet, enqueue the callback to be fired when | 157 // If the key hasn't been loaded yet, enqueue the callback to be fired when |
| 151 // the next SessionManagerOperation completes. If no operation is pending, | 158 // the next SessionManagerOperation completes. If no operation is pending, |
| 152 // start a load operation to fetch the key and report the result. | 159 // start a load operation to fetch the key and report the result. |
| 153 pending_ownership_status_callbacks_.push_back(callback); | 160 pending_ownership_status_callbacks_.push_back(callback); |
| 154 if (pending_operations_.empty()) | 161 if (pending_operations_.empty()) |
| 155 EnqueueLoad(false); | 162 EnqueueLoad(false); |
| 156 } | 163 } |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 210 EnsureReload(false); | 217 EnsureReload(false); |
| 211 } | 218 } |
| 212 | 219 |
| 213 void DeviceSettingsService::Enqueue( | 220 void DeviceSettingsService::Enqueue( |
| 214 const linked_ptr<SessionManagerOperation>& operation) { | 221 const linked_ptr<SessionManagerOperation>& operation) { |
| 215 pending_operations_.push_back(operation); | 222 pending_operations_.push_back(operation); |
| 216 if (pending_operations_.front().get() == operation.get()) | 223 if (pending_operations_.front().get() == operation.get()) |
| 217 StartNextOperation(); | 224 StartNextOperation(); |
| 218 } | 225 } |
| 219 | 226 |
| 220 void DeviceSettingsService::EnqueueLoad(bool force_key_load) { | 227 void DeviceSettingsService::EnqueueLoad(bool request_key_load) { |
| 228 bool verify_signature = true; | |
| 229 if (device_mode_ == policy::DEVICE_MODE_ENTERPRISE_AD) { | |
| 230 request_key_load = false; | |
| 231 verify_signature = false; | |
| 232 } | |
| 221 linked_ptr<SessionManagerOperation> operation(new LoadSettingsOperation( | 233 linked_ptr<SessionManagerOperation> operation(new LoadSettingsOperation( |
| 234 request_key_load, verify_signature, | |
| 222 base::Bind(&DeviceSettingsService::HandleCompletedOperation, | 235 base::Bind(&DeviceSettingsService::HandleCompletedOperation, |
| 223 weak_factory_.GetWeakPtr(), | 236 weak_factory_.GetWeakPtr(), base::Closure()))); |
| 224 base::Closure()))); | |
| 225 operation->set_force_key_load(force_key_load); | |
| 226 Enqueue(operation); | 237 Enqueue(operation); |
| 227 } | 238 } |
| 228 | 239 |
| 229 void DeviceSettingsService::EnsureReload(bool force_key_load) { | 240 void DeviceSettingsService::EnsureReload(bool request_key_load) { |
| 230 if (!pending_operations_.empty()) | 241 if (!pending_operations_.empty()) |
| 231 pending_operations_.front()->RestartLoad(force_key_load); | 242 pending_operations_.front()->RestartLoad(request_key_load); |
| 232 else | 243 else |
| 233 EnqueueLoad(force_key_load); | 244 EnqueueLoad(request_key_load); |
| 234 } | 245 } |
| 235 | 246 |
| 236 void DeviceSettingsService::StartNextOperation() { | 247 void DeviceSettingsService::StartNextOperation() { |
| 237 if (!pending_operations_.empty() && session_manager_client_ && | 248 if (!pending_operations_.empty() && session_manager_client_ && |
| 238 owner_key_util_.get()) { | 249 owner_key_util_.get()) { |
| 239 pending_operations_.front()->Start( | 250 pending_operations_.front()->Start( |
| 240 session_manager_client_, owner_key_util_, public_key_); | 251 session_manager_client_, owner_key_util_, public_key_); |
| 241 } | 252 } |
| 242 } | 253 } |
| 243 | 254 |
| 244 void DeviceSettingsService::HandleCompletedOperation( | 255 void DeviceSettingsService::HandleCompletedOperation( |
| 245 const base::Closure& callback, | 256 const base::Closure& callback, |
| 246 SessionManagerOperation* operation, | 257 SessionManagerOperation* operation, |
| 247 Status status) { | 258 Status status) { |
| 259 // Exactly one must be true: Active Directory management or existence of key. | |
| 260 DCHECK((device_mode_ == policy::DEVICE_MODE_ENTERPRISE_AD) != | |
|
emaxx
2016/11/17 01:14:32
nit: Use DCHECK_NE or DCHECK_EQ? This will print t
Thiemo Nagel
2016/11/17 14:19:07
Good point. Done.
| |
| 261 (operation->public_key() != nullptr)); | |
| 248 DCHECK_EQ(operation, pending_operations_.front().get()); | 262 DCHECK_EQ(operation, pending_operations_.front().get()); |
| 263 | |
| 249 store_status_ = status; | 264 store_status_ = status; |
| 250 | |
| 251 OwnershipStatus ownership_status = OWNERSHIP_UNKNOWN; | |
| 252 scoped_refptr<PublicKey> new_key(operation->public_key()); | |
| 253 if (new_key.get()) { | |
| 254 ownership_status = new_key->is_loaded() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE; | |
| 255 } else { | |
| 256 NOTREACHED() << "Failed to determine key status."; | |
| 257 } | |
| 258 | |
| 259 bool new_owner_key = false; | |
| 260 if (public_key_.get() != new_key.get()) { | |
| 261 public_key_ = new_key; | |
| 262 new_owner_key = true; | |
| 263 } | |
| 264 | |
| 265 if (status == STORE_SUCCESS) { | 265 if (status == STORE_SUCCESS) { |
| 266 policy_data_ = std::move(operation->policy_data()); | 266 policy_data_ = std::move(operation->policy_data()); |
| 267 device_settings_ = std::move(operation->device_settings()); | 267 device_settings_ = std::move(operation->device_settings()); |
| 268 load_retries_left_ = kMaxLoadRetries; | 268 load_retries_left_ = kMaxLoadRetries; |
| 269 } else if (status != STORE_KEY_UNAVAILABLE) { | 269 } else if (status != STORE_KEY_UNAVAILABLE) { |
| 270 LOG(ERROR) << "Session manager operation failed: " << status; | 270 LOG(ERROR) << "Session manager operation failed: " << status; |
| 271 // Validation errors can be temporary if the rtc has gone on holiday for a | 271 // Validation errors can be temporary if the rtc has gone on holiday for a |
| 272 // short while. So we will retry such loads for up to 10 minutes. | 272 // short while. So we will retry such loads for up to 10 minutes. |
| 273 if (status == STORE_TEMP_VALIDATION_ERROR) { | 273 if (status == STORE_TEMP_VALIDATION_ERROR) { |
| 274 if (load_retries_left_ > 0) { | 274 if (load_retries_left_ > 0) { |
| 275 load_retries_left_--; | 275 load_retries_left_--; |
| 276 LOG(ERROR) << "A re-load has been scheduled due to a validation error."; | 276 LOG(ERROR) << "A re-load has been scheduled due to a validation error."; |
| 277 content::BrowserThread::PostDelayedTask( | 277 content::BrowserThread::PostDelayedTask( |
| 278 content::BrowserThread::UI, | 278 content::BrowserThread::UI, |
| 279 FROM_HERE, | 279 FROM_HERE, |
| 280 base::Bind(&DeviceSettingsService::Load, base::Unretained(this)), | 280 base::Bind(&DeviceSettingsService::Load, base::Unretained(this)), |
| 281 base::TimeDelta::FromMilliseconds(kLoadRetryDelayMs)); | 281 base::TimeDelta::FromMilliseconds(kLoadRetryDelayMs)); |
| 282 } else { | 282 } else { |
| 283 // Once we've given up retrying, the validation error is not temporary | 283 // Once we've given up retrying, the validation error is not temporary |
| 284 // anymore. | 284 // anymore. |
| 285 store_status_ = STORE_VALIDATION_ERROR; | 285 store_status_ = STORE_VALIDATION_ERROR; |
| 286 } | 286 } |
| 287 } | 287 } |
| 288 } | 288 } |
| 289 | 289 |
| 290 if (new_owner_key) { | 290 public_key_ = scoped_refptr<PublicKey>(operation->public_key()); |
| 291 for (auto& observer : observers_) | 291 if (GetOwnershipStatus() != previous_ownership_status_) { |
| 292 observer.OwnershipStatusChanged(); | 292 previous_ownership_status_ = GetOwnershipStatus(); |
| 293 content::NotificationService::current()->Notify( | 293 NotifyOwnershipStatusChanged(); |
| 294 chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED, | |
| 295 content::Source<DeviceSettingsService>(this), | |
| 296 content::NotificationService::NoDetails()); | |
| 297 } | 294 } |
| 298 | 295 NotifyDeviceSettingsUpdated(); |
| 299 for (auto& observer : observers_) | 296 RunPendingOwnershipStatusCallbacks(); |
| 300 observer.DeviceSettingsUpdated(); | |
| 301 | |
| 302 std::vector<OwnershipStatusCallback> callbacks; | |
| 303 callbacks.swap(pending_ownership_status_callbacks_); | |
| 304 for (std::vector<OwnershipStatusCallback>::iterator iter(callbacks.begin()); | |
| 305 iter != callbacks.end(); ++iter) { | |
| 306 iter->Run(ownership_status); | |
| 307 } | |
| 308 | 297 |
| 309 // The completion callback happens after the notification so clients can | 298 // The completion callback happens after the notification so clients can |
| 310 // filter self-triggered updates. | 299 // filter self-triggered updates. |
| 311 if (!callback.is_null()) | 300 if (!callback.is_null()) |
| 312 callback.Run(); | 301 callback.Run(); |
| 313 | 302 |
| 314 // Only remove the pending operation here, so new operations triggered by any | 303 // Only remove the pending operation here, so new operations triggered by any |
| 315 // of the callbacks above are queued up properly. | 304 // of the callbacks above are queued up properly. |
| 316 pending_operations_.pop_front(); | 305 pending_operations_.pop_front(); |
| 317 | 306 |
| 318 StartNextOperation(); | 307 StartNextOperation(); |
| 319 } | 308 } |
| 320 | 309 |
| 321 void DeviceSettingsService::HandleError(Status status, | 310 void DeviceSettingsService::HandleError(Status status, |
| 322 const base::Closure& callback) { | 311 const base::Closure& callback) { |
| 323 store_status_ = status; | 312 store_status_ = status; |
| 324 | |
| 325 LOG(ERROR) << "Session manager operation failed: " << status; | 313 LOG(ERROR) << "Session manager operation failed: " << status; |
| 326 | 314 NotifyDeviceSettingsUpdated(); |
| 327 for (auto& observer : observers_) | |
| 328 observer.DeviceSettingsUpdated(); | |
| 329 | 315 |
| 330 // The completion callback happens after the notification so clients can | 316 // The completion callback happens after the notification so clients can |
| 331 // filter self-triggered updates. | 317 // filter self-triggered updates. |
| 332 if (!callback.is_null()) | 318 if (!callback.is_null()) |
| 333 callback.Run(); | 319 callback.Run(); |
| 334 } | 320 } |
| 335 | 321 |
| 322 void DeviceSettingsService::NotifyOwnershipStatusChanged() const { | |
| 323 for (auto& observer : observers_) { | |
| 324 observer.OwnershipStatusChanged(); | |
| 325 } | |
| 326 content::NotificationService::current()->Notify( | |
| 327 chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED, | |
| 328 content::Source<DeviceSettingsService>(this), | |
| 329 content::NotificationService::NoDetails()); | |
| 330 } | |
| 331 | |
| 332 void DeviceSettingsService::NotifyDeviceSettingsUpdated() const { | |
| 333 for (auto& observer : observers_) | |
| 334 observer.DeviceSettingsUpdated(); | |
| 335 } | |
| 336 | |
| 337 void DeviceSettingsService::RunPendingOwnershipStatusCallbacks() { | |
| 338 std::vector<OwnershipStatusCallback> callbacks; | |
| 339 callbacks.swap(pending_ownership_status_callbacks_); | |
| 340 for (const auto& callback : callbacks) { | |
| 341 callback.Run(GetOwnershipStatus()); | |
| 342 } | |
| 343 } | |
| 344 | |
| 336 ScopedTestDeviceSettingsService::ScopedTestDeviceSettingsService() { | 345 ScopedTestDeviceSettingsService::ScopedTestDeviceSettingsService() { |
| 337 DeviceSettingsService::Initialize(); | 346 DeviceSettingsService::Initialize(); |
| 338 } | 347 } |
| 339 | 348 |
| 340 ScopedTestDeviceSettingsService::~ScopedTestDeviceSettingsService() { | 349 ScopedTestDeviceSettingsService::~ScopedTestDeviceSettingsService() { |
| 341 // Clean pending operations. | 350 // Clean pending operations. |
| 342 DeviceSettingsService::Get()->UnsetSessionManager(); | 351 DeviceSettingsService::Get()->UnsetSessionManager(); |
| 343 DeviceSettingsService::Shutdown(); | 352 DeviceSettingsService::Shutdown(); |
| 344 } | 353 } |
| 345 | 354 |
| 346 } // namespace chromeos | 355 } // namespace chromeos |
| OLD | NEW |