Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / settings / device_settings_service.cc
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 "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"
20
21 namespace em = enterprise_management;
22
23 namespace {
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.
29 int kLoadRetryDelayMs = 1000 * 5;
30 // Maximal number of retries before we give up. Calculated to allow for 10 min
31 // of retry time.
32 int kMaxLoadRetries = (1000 * 60 * 10) / kLoadRetryDelayMs;
33
34 }  // namespace
35
36 namespace chromeos {
37
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()) {}
42
43 OwnerKey::~OwnerKey() {}
44
45 DeviceSettingsService::Observer::~Observer() {}
46
47 static DeviceSettingsService* g_device_settings_service = NULL;
48
49 // static
50 void DeviceSettingsService::Initialize() {
51   CHECK(!g_device_settings_service);
52   g_device_settings_service = new DeviceSettingsService();
53 }
54
55 // static
56 bool DeviceSettingsService::IsInitialized() {
57   return g_device_settings_service;
58 }
59
60 // static
61 void DeviceSettingsService::Shutdown() {
62   DCHECK(g_device_settings_service);
63   delete g_device_settings_service;
64   g_device_settings_service = NULL;
65 }
66
67 // static
68 DeviceSettingsService* DeviceSettingsService::Get() {
69   CHECK(g_device_settings_service);
70   return g_device_settings_service;
71 }
72
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),
79       weak_factory_(this) {
80   if (TPMTokenLoader::IsInitialized()) {
81     waiting_for_tpm_token_ = !TPMTokenLoader::Get()->IsTPMTokenReady();
82     TPMTokenLoader::Get()->AddObserver(this);
83   }
84 }
85
86 DeviceSettingsService::~DeviceSettingsService() {
87   DCHECK(pending_operations_.empty());
88   if (TPMTokenLoader::IsInitialized())
89     TPMTokenLoader::Get()->RemoveObserver(this);
90 }
91
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());
99
100   session_manager_client_ = session_manager_client;
101   owner_key_util_ = owner_key_util;
102
103   session_manager_client_->AddObserver(this);
104
105   StartNextOperation();
106 }
107
108 void DeviceSettingsService::UnsetSessionManager() {
109   STLDeleteContainerPointers(pending_operations_.begin(),
110                              pending_operations_.end());
111   pending_operations_.clear();
112
113   if (session_manager_client_)
114     session_manager_client_->RemoveObserver(this);
115   session_manager_client_ = NULL;
116   owner_key_util_ = NULL;
117 }
118
119 scoped_refptr<OwnerKey> DeviceSettingsService::GetOwnerKey() {
120   return owner_key_;
121 }
122
123 void DeviceSettingsService::Load() {
124   EnqueueLoad(false);
125 }
126
127 void DeviceSettingsService::SignAndStore(
128     scoped_ptr<em::ChromeDeviceSettingsProto> new_settings,
129     const base::Closure& callback) {
130   Enqueue(
131       new SignAndStoreSettingsOperation(
132           base::Bind(&DeviceSettingsService::HandleCompletedOperation,
133                      weak_factory_.GetWeakPtr(),
134                      callback),
135           new_settings.Pass(),
136           username_));
137 }
138
139 void DeviceSettingsService::Store(scoped_ptr<em::PolicyFetchResponse> policy,
140                                   const base::Closure& callback) {
141   Enqueue(
142       new StoreSettingsOperation(
143           base::Bind(&DeviceSettingsService::HandleCompletedOperation,
144                      weak_factory_.GetWeakPtr(),
145                      callback),
146           policy.Pass()));
147 }
148
149 DeviceSettingsService::OwnershipStatus
150     DeviceSettingsService::GetOwnershipStatus() {
151   if (owner_key_.get())
152     return owner_key_->public_key() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE;
153
154   return OWNERSHIP_UNKNOWN;
155 }
156
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(
162         FROM_HERE,
163         base::Bind(
164             callback,
165             owner_key_->public_key() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE));
166   } else {
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())
172       EnqueueLoad(false);
173   }
174 }
175
176 bool DeviceSettingsService::HasPrivateOwnerKey() {
177   return owner_key_.get() && owner_key_->private_key();
178 }
179
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(
187         FROM_HERE,
188         base::Bind(callback, HasPrivateOwnerKey()));
189   } else {
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);
196   }
197 }
198
199 void DeviceSettingsService::SetUsername(const std::string& username) {
200   username_ = username;
201
202   // The private key may have become available, so force a key reload.
203   owner_key_ = NULL;
204   EnsureReload(true);
205 }
206
207 const std::string& DeviceSettingsService::GetUsername() const {
208   return username_;
209 }
210
211 void DeviceSettingsService::AddObserver(Observer* observer) {
212   observers_.AddObserver(observer);
213 }
214
215 void DeviceSettingsService::RemoveObserver(Observer* observer) {
216   observers_.RemoveObserver(observer);
217 }
218
219 void DeviceSettingsService::OwnerKeySet(bool success) {
220   if (!success) {
221     LOG(ERROR) << "Owner key change failed.";
222     return;
223   }
224
225   owner_key_ = NULL;
226   EnsureReload(true);
227 }
228
229 void DeviceSettingsService::PropertyChangeComplete(bool success) {
230   if (!success) {
231     LOG(ERROR) << "Policy update failed.";
232     return;
233   }
234
235   EnsureReload(false);
236 }
237
238 void DeviceSettingsService::OnTPMTokenReady() {
239   waiting_for_tpm_token_ = false;
240
241   // TPMTokenLoader initializes the TPM and NSS database which is necessary to
242   // determine ownership. Force a reload once we know these are initialized.
243   EnsureReload(true);
244 }
245
246 void DeviceSettingsService::Enqueue(SessionManagerOperation* operation) {
247   pending_operations_.push_back(operation);
248   if (pending_operations_.front() == operation)
249     StartNextOperation();
250 }
251
252 void DeviceSettingsService::EnqueueLoad(bool force_key_load) {
253   SessionManagerOperation* operation =
254       new LoadSettingsOperation(
255           base::Bind(&DeviceSettingsService::HandleCompletedOperation,
256                      weak_factory_.GetWeakPtr(),
257                      base::Closure()));
258   operation->set_force_key_load(force_key_load);
259   Enqueue(operation);
260 }
261
262 void DeviceSettingsService::EnsureReload(bool force_key_load) {
263   if (!pending_operations_.empty())
264     pending_operations_.front()->RestartLoad(force_key_load);
265   else
266     EnqueueLoad(force_key_load);
267 }
268
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_);
275   }
276 }
277
278 void DeviceSettingsService::HandleCompletedOperation(
279     const base::Closure& callback,
280     SessionManagerOperation* operation,
281     Status status) {
282   DCHECK_EQ(operation, pending_operations_.front());
283   store_status_ = status;
284
285   OwnershipStatus ownership_status = OWNERSHIP_UNKNOWN;
286   bool is_owner = false;
287   scoped_refptr<OwnerKey> new_key(operation->owner_key());
288   if (new_key.get()) {
289     ownership_status =
290         new_key->public_key() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE;
291     is_owner = (new_key->private_key() != NULL);
292   } else {
293     NOTREACHED() << "Failed to determine key status.";
294   }
295
296   bool new_owner_key = false;
297   if (owner_key_.get() != new_key.get()) {
298     owner_key_ = new_key;
299     new_owner_key = true;
300   }
301
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,
316             FROM_HERE,
317             base::Bind(&DeviceSettingsService::Load, base::Unretained(this)),
318             base::TimeDelta::FromMilliseconds(kLoadRetryDelayMs));
319       }
320     }
321   }
322
323   if (new_owner_key) {
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());
329   }
330
331   FOR_EACH_OBSERVER(Observer, observers_, DeviceSettingsUpdated());
332
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);
338   }
339
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) {
347       iter->Run(is_owner);
348     }
349   }
350
351   // The completion callback happens after the notification so clients can
352   // filter self-triggered updates.
353   if (!callback.is_null())
354     callback.Run();
355
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();
359   delete operation;
360
361   StartNextOperation();
362 }
363
364 ScopedTestDeviceSettingsService::ScopedTestDeviceSettingsService() {
365   DeviceSettingsService::Initialize();
366 }
367
368 ScopedTestDeviceSettingsService::~ScopedTestDeviceSettingsService() {
369   // Clean pending operations.
370   DeviceSettingsService::Get()->UnsetSessionManager();
371   DeviceSettingsService::Shutdown();
372 }
373
374 }  // namespace chromeos