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.
5 #include "chrome/browser/chromeos/settings/device_settings_service.h"
8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/stl_util.h"
11 #include "chrome/browser/chrome_notification_types.h"
12 #include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
13 #include "chrome/browser/chromeos/settings/owner_key_util.h"
14 #include "chrome/browser/chromeos/settings/session_manager_operation.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "content/public/browser/notification_service.h"
17 #include "content/public/browser/notification_source.h"
18 #include "crypto/rsa_private_key.h"
19 #include "policy/proto/device_management_backend.pb.h"
21 namespace em
= enterprise_management
;
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.
29 int kLoadRetryDelayMs
= 1000 * 5;
30 // Maximal number of retries before we give up. Calculated to allow for 10 min
32 int kMaxLoadRetries
= (1000 * 60 * 10) / kLoadRetryDelayMs
;
38 OwnerKey::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()) {}
43 OwnerKey::~OwnerKey() {}
45 DeviceSettingsService::Observer::~Observer() {}
47 static DeviceSettingsService
* g_device_settings_service
= NULL
;
50 void DeviceSettingsService::Initialize() {
51 CHECK(!g_device_settings_service
);
52 g_device_settings_service
= new DeviceSettingsService();
56 bool DeviceSettingsService::IsInitialized() {
57 return g_device_settings_service
;
61 void DeviceSettingsService::Shutdown() {
62 DCHECK(g_device_settings_service
);
63 delete g_device_settings_service
;
64 g_device_settings_service
= NULL
;
68 DeviceSettingsService
* DeviceSettingsService::Get() {
69 CHECK(g_device_settings_service
);
70 return g_device_settings_service
;
73 DeviceSettingsService::DeviceSettingsService()
74 : session_manager_client_(NULL
),
75 store_status_(STORE_SUCCESS
),
76 waiting_for_tpm_token_(true),
77 owner_key_loaded_with_tpm_token_(false),
78 load_retries_left_(kMaxLoadRetries
),
80 if (TPMTokenLoader::IsInitialized()) {
81 waiting_for_tpm_token_
= !TPMTokenLoader::Get()->IsTPMTokenReady();
82 TPMTokenLoader::Get()->AddObserver(this);
86 DeviceSettingsService::~DeviceSettingsService() {
87 DCHECK(pending_operations_
.empty());
88 if (TPMTokenLoader::IsInitialized())
89 TPMTokenLoader::Get()->RemoveObserver(this);
92 void DeviceSettingsService::SetSessionManager(
93 SessionManagerClient
* session_manager_client
,
94 scoped_refptr
<OwnerKeyUtil
> owner_key_util
) {
95 DCHECK(session_manager_client
);
96 DCHECK(owner_key_util
.get());
97 DCHECK(!session_manager_client_
);
98 DCHECK(!owner_key_util_
.get());
100 session_manager_client_
= session_manager_client
;
101 owner_key_util_
= owner_key_util
;
103 session_manager_client_
->AddObserver(this);
105 StartNextOperation();
108 void DeviceSettingsService::UnsetSessionManager() {
109 STLDeleteContainerPointers(pending_operations_
.begin(),
110 pending_operations_
.end());
111 pending_operations_
.clear();
113 if (session_manager_client_
)
114 session_manager_client_
->RemoveObserver(this);
115 session_manager_client_
= NULL
;
116 owner_key_util_
= NULL
;
119 scoped_refptr
<OwnerKey
> DeviceSettingsService::GetOwnerKey() {
123 void DeviceSettingsService::Load() {
127 void DeviceSettingsService::SignAndStore(
128 scoped_ptr
<em::ChromeDeviceSettingsProto
> new_settings
,
129 const base::Closure
& callback
) {
131 new SignAndStoreSettingsOperation(
132 base::Bind(&DeviceSettingsService::HandleCompletedOperation
,
133 weak_factory_
.GetWeakPtr(),
139 void DeviceSettingsService::Store(scoped_ptr
<em::PolicyFetchResponse
> policy
,
140 const base::Closure
& callback
) {
142 new StoreSettingsOperation(
143 base::Bind(&DeviceSettingsService::HandleCompletedOperation
,
144 weak_factory_
.GetWeakPtr(),
149 DeviceSettingsService::OwnershipStatus
150 DeviceSettingsService::GetOwnershipStatus() {
151 if (owner_key_
.get())
152 return owner_key_
->public_key() ? OWNERSHIP_TAKEN
: OWNERSHIP_NONE
;
154 return OWNERSHIP_UNKNOWN
;
157 void DeviceSettingsService::GetOwnershipStatusAsync(
158 const OwnershipStatusCallback
& callback
) {
159 if (owner_key_
.get()) {
160 // If there is a key, report status immediately.
161 base::MessageLoop::current()->PostTask(
165 owner_key_
->public_key() ? OWNERSHIP_TAKEN
: OWNERSHIP_NONE
));
167 // If the key hasn't been loaded yet, enqueue the callback to be fired when
168 // the next SessionManagerOperation completes. If no operation is pending,
169 // start a load operation to fetch the key and report the result.
170 pending_ownership_status_callbacks_
.push_back(callback
);
171 if (pending_operations_
.empty())
176 bool DeviceSettingsService::HasPrivateOwnerKey() {
177 return owner_key_
.get() && owner_key_
->private_key();
180 void DeviceSettingsService::IsCurrentUserOwnerAsync(
181 const IsCurrentUserOwnerCallback
& callback
) {
182 if (owner_key_loaded_with_tpm_token_
) {
183 // If the current owner key was loaded while the certificates were loaded,
184 // or the certificate loader is not initialized, in which case the private
185 // key cannot be set, report status immediately.
186 base::MessageLoop::current()->PostTask(
188 base::Bind(callback
, HasPrivateOwnerKey()));
190 // If the key hasn't been loaded with the known certificates, enqueue the
191 // callback to be fired when the next SessionManagerOperation completes in
192 // an environment where the certificates are loaded. There is no need to
193 // start a new operation, as the reload operation will be started when the
194 // certificates are loaded.
195 pending_is_current_user_owner_callbacks_
.push_back(callback
);
199 void DeviceSettingsService::SetUsername(const std::string
& username
) {
200 username_
= username
;
202 // The private key may have become available, so force a key reload.
207 const std::string
& DeviceSettingsService::GetUsername() const {
211 void DeviceSettingsService::AddObserver(Observer
* observer
) {
212 observers_
.AddObserver(observer
);
215 void DeviceSettingsService::RemoveObserver(Observer
* observer
) {
216 observers_
.RemoveObserver(observer
);
219 void DeviceSettingsService::OwnerKeySet(bool success
) {
221 LOG(ERROR
) << "Owner key change failed.";
229 void DeviceSettingsService::PropertyChangeComplete(bool success
) {
231 LOG(ERROR
) << "Policy update failed.";
238 void DeviceSettingsService::OnTPMTokenReady() {
239 waiting_for_tpm_token_
= false;
241 // TPMTokenLoader initializes the TPM and NSS database which is necessary to
242 // determine ownership. Force a reload once we know these are initialized.
246 void DeviceSettingsService::Enqueue(SessionManagerOperation
* operation
) {
247 pending_operations_
.push_back(operation
);
248 if (pending_operations_
.front() == operation
)
249 StartNextOperation();
252 void DeviceSettingsService::EnqueueLoad(bool force_key_load
) {
253 SessionManagerOperation
* operation
=
254 new LoadSettingsOperation(
255 base::Bind(&DeviceSettingsService::HandleCompletedOperation
,
256 weak_factory_
.GetWeakPtr(),
258 operation
->set_force_key_load(force_key_load
);
262 void DeviceSettingsService::EnsureReload(bool force_key_load
) {
263 if (!pending_operations_
.empty())
264 pending_operations_
.front()->RestartLoad(force_key_load
);
266 EnqueueLoad(force_key_load
);
269 void DeviceSettingsService::StartNextOperation() {
270 if (!pending_operations_
.empty() &&
271 session_manager_client_
&&
272 owner_key_util_
.get()) {
273 pending_operations_
.front()->Start(session_manager_client_
,
274 owner_key_util_
, owner_key_
);
278 void DeviceSettingsService::HandleCompletedOperation(
279 const base::Closure
& callback
,
280 SessionManagerOperation
* operation
,
282 DCHECK_EQ(operation
, pending_operations_
.front());
283 store_status_
= status
;
285 OwnershipStatus ownership_status
= OWNERSHIP_UNKNOWN
;
286 bool is_owner
= false;
287 scoped_refptr
<OwnerKey
> new_key(operation
->owner_key());
290 new_key
->public_key() ? OWNERSHIP_TAKEN
: OWNERSHIP_NONE
;
291 is_owner
= (new_key
->private_key() != NULL
);
293 NOTREACHED() << "Failed to determine key status.";
296 bool new_owner_key
= false;
297 if (owner_key_
.get() != new_key
.get()) {
298 owner_key_
= new_key
;
299 new_owner_key
= true;
302 if (status
== STORE_SUCCESS
) {
303 policy_data_
= operation
->policy_data().Pass();
304 device_settings_
= operation
->device_settings().Pass();
305 load_retries_left_
= kMaxLoadRetries
;
306 } else if (status
!= STORE_KEY_UNAVAILABLE
) {
307 LOG(ERROR
) << "Session manager operation failed: " << status
;
308 // Validation errors can be temprary if the rtc has went on holiday for a
309 // short while. So we will retry such loads for up to 10 minutes.
310 if (status
== STORE_TEMP_VALIDATION_ERROR
) {
311 if (load_retries_left_
> 0) {
312 load_retries_left_
--;
313 LOG(ERROR
) << "A re-load has been scheduled due to a validation error.";
314 content::BrowserThread::PostDelayedTask(
315 content::BrowserThread::UI
,
317 base::Bind(&DeviceSettingsService::Load
, base::Unretained(this)),
318 base::TimeDelta::FromMilliseconds(kLoadRetryDelayMs
));
324 FOR_EACH_OBSERVER(Observer
, observers_
, OwnershipStatusChanged());
325 content::NotificationService::current()->Notify(
326 chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED
,
327 content::Source
<DeviceSettingsService
>(this),
328 content::NotificationService::NoDetails());
331 FOR_EACH_OBSERVER(Observer
, observers_
, DeviceSettingsUpdated());
333 std::vector
<OwnershipStatusCallback
> callbacks
;
334 callbacks
.swap(pending_ownership_status_callbacks_
);
335 for (std::vector
<OwnershipStatusCallback
>::iterator
iter(callbacks
.begin());
336 iter
!= callbacks
.end(); ++iter
) {
337 iter
->Run(ownership_status
);
340 if (!waiting_for_tpm_token_
) {
341 owner_key_loaded_with_tpm_token_
= true;
342 std::vector
<IsCurrentUserOwnerCallback
> is_owner_callbacks
;
343 is_owner_callbacks
.swap(pending_is_current_user_owner_callbacks_
);
344 for (std::vector
<IsCurrentUserOwnerCallback
>::iterator
iter(
345 is_owner_callbacks
.begin());
346 iter
!= is_owner_callbacks
.end(); ++iter
) {
351 // The completion callback happens after the notification so clients can
352 // filter self-triggered updates.
353 if (!callback
.is_null())
356 // Only remove the pending operation here, so new operations triggered by any
357 // of the callbacks above are queued up properly.
358 pending_operations_
.pop_front();
361 StartNextOperation();
364 ScopedTestDeviceSettingsService::ScopedTestDeviceSettingsService() {
365 DeviceSettingsService::Initialize();
368 ScopedTestDeviceSettingsService::~ScopedTestDeviceSettingsService() {
369 // Clean pending operations.
370 DeviceSettingsService::Get()->UnsetSessionManager();
371 DeviceSettingsService::Shutdown();
374 } // namespace chromeos