device_settings_service.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
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
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      certificates_loaded_(false),
78      owner_key_loaded_with_certificates_(false),
79      load_retries_left_(kMaxLoadRetries) {
80  if (CertLoader::IsInitialized()) {
81    certificates_loaded_ = CertLoader::Get()->certificates_loaded();
82    CertLoader::Get()->AddObserver(this);
83  }
84}
85
86DeviceSettingsService::~DeviceSettingsService() {
87  DCHECK(pending_operations_.empty());
88  if (CertLoader::IsInitialized())
89    CertLoader::Get()->RemoveObserver(this);
90}
91
92void 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
108void 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
119scoped_refptr<OwnerKey> DeviceSettingsService::GetOwnerKey() {
120  return owner_key_;
121}
122
123void DeviceSettingsService::Load() {
124  EnqueueLoad(false);
125}
126
127void 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
139void 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
149DeviceSettingsService::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
157void 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
176bool DeviceSettingsService::HasPrivateOwnerKey() {
177  return owner_key_.get() && owner_key_->private_key();
178}
179
180void DeviceSettingsService::IsCurrentUserOwnerAsync(
181    const IsCurrentUserOwnerCallback& callback) {
182  if (owner_key_loaded_with_certificates_) {
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
199void 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
207const std::string& DeviceSettingsService::GetUsername() const {
208  return username_;
209}
210
211void DeviceSettingsService::AddObserver(Observer* observer) {
212  observers_.AddObserver(observer);
213}
214
215void DeviceSettingsService::RemoveObserver(Observer* observer) {
216  observers_.RemoveObserver(observer);
217}
218
219void 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
229void DeviceSettingsService::PropertyChangeComplete(bool success) {
230  if (!success) {
231    LOG(ERROR) << "Policy update failed.";
232    return;
233  }
234
235  EnsureReload(false);
236}
237
238void DeviceSettingsService::OnCertificatesLoaded(
239    const net::CertificateList& cert_list,
240    bool initial_load) {
241  certificates_loaded_ = true;
242  // CertLoader initializes the TPM and NSS database which is necessary to
243  // determine ownership. Force a reload once we know these are initialized.
244  EnsureReload(true);
245}
246
247void DeviceSettingsService::Enqueue(SessionManagerOperation* operation) {
248  pending_operations_.push_back(operation);
249  if (pending_operations_.front() == operation)
250    StartNextOperation();
251}
252
253void DeviceSettingsService::EnqueueLoad(bool force_key_load) {
254  SessionManagerOperation* operation =
255      new LoadSettingsOperation(
256          base::Bind(&DeviceSettingsService::HandleCompletedOperation,
257                     weak_factory_.GetWeakPtr(),
258                     base::Closure()));
259  operation->set_force_key_load(force_key_load);
260  Enqueue(operation);
261}
262
263void DeviceSettingsService::EnsureReload(bool force_key_load) {
264  if (!pending_operations_.empty())
265    pending_operations_.front()->RestartLoad(force_key_load);
266  else
267    EnqueueLoad(force_key_load);
268}
269
270void DeviceSettingsService::StartNextOperation() {
271  if (!pending_operations_.empty() &&
272      session_manager_client_ &&
273      owner_key_util_.get()) {
274    pending_operations_.front()->Start(session_manager_client_,
275                                       owner_key_util_, owner_key_);
276  }
277}
278
279void DeviceSettingsService::HandleCompletedOperation(
280    const base::Closure& callback,
281    SessionManagerOperation* operation,
282    Status status) {
283  DCHECK_EQ(operation, pending_operations_.front());
284  store_status_ = status;
285
286  OwnershipStatus ownership_status = OWNERSHIP_UNKNOWN;
287  bool is_owner = false;
288  scoped_refptr<OwnerKey> new_key(operation->owner_key());
289  if (new_key.get()) {
290    ownership_status =
291        new_key->public_key() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE;
292    is_owner = (new_key->private_key() != NULL);
293  } else {
294    NOTREACHED() << "Failed to determine key status.";
295  }
296
297  bool new_owner_key = false;
298  if (owner_key_.get() != new_key.get()) {
299    owner_key_ = new_key;
300    new_owner_key = true;
301  }
302
303  if (status == STORE_SUCCESS) {
304    policy_data_ = operation->policy_data().Pass();
305    device_settings_ = operation->device_settings().Pass();
306    load_retries_left_ = kMaxLoadRetries;
307  } else if (status != STORE_KEY_UNAVAILABLE) {
308    LOG(ERROR) << "Session manager operation failed: " << status;
309    // Validation errors can be temprary if the rtc has went on holiday for a
310    // short while. So we will retry such loads for up to 10 minutes.
311    if (status == STORE_TEMP_VALIDATION_ERROR) {
312      if (load_retries_left_ > 0) {
313        load_retries_left_--;
314        LOG(ERROR) << "A re-load has been scheduled due to a validation error.";
315        content::BrowserThread::PostDelayedTask(
316            content::BrowserThread::UI,
317            FROM_HERE,
318            base::Bind(&DeviceSettingsService::Load, base::Unretained(this)),
319            base::TimeDelta::FromMilliseconds(kLoadRetryDelayMs));
320      }
321    }
322  }
323
324  if (new_owner_key) {
325    FOR_EACH_OBSERVER(Observer, observers_, OwnershipStatusChanged());
326    content::NotificationService::current()->Notify(
327        chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED,
328        content::Source<DeviceSettingsService>(this),
329        content::NotificationService::NoDetails());
330  }
331
332  FOR_EACH_OBSERVER(Observer, observers_, DeviceSettingsUpdated());
333
334  std::vector<OwnershipStatusCallback> callbacks;
335  callbacks.swap(pending_ownership_status_callbacks_);
336  for (std::vector<OwnershipStatusCallback>::iterator iter(callbacks.begin());
337       iter != callbacks.end(); ++iter) {
338    iter->Run(ownership_status);
339  }
340
341  if (certificates_loaded_) {
342    owner_key_loaded_with_certificates_ = true;
343    std::vector<IsCurrentUserOwnerCallback> is_owner_callbacks;
344    is_owner_callbacks.swap(pending_is_current_user_owner_callbacks_);
345    for (std::vector<IsCurrentUserOwnerCallback>::iterator iter(
346             is_owner_callbacks.begin());
347         iter != is_owner_callbacks.end(); ++iter) {
348      iter->Run(is_owner);
349    }
350  }
351
352  // The completion callback happens after the notification so clients can
353  // filter self-triggered updates.
354  if (!callback.is_null())
355    callback.Run();
356
357  // Only remove the pending operation here, so new operations triggered by any
358  // of the callbacks above are queued up properly.
359  pending_operations_.pop_front();
360  delete operation;
361
362  StartNextOperation();
363}
364
365ScopedTestDeviceSettingsService::ScopedTestDeviceSettingsService() {
366  DeviceSettingsService::Initialize();
367}
368
369ScopedTestDeviceSettingsService::~ScopedTestDeviceSettingsService() {
370  DeviceSettingsService::Shutdown();
371}
372
373}  // namespace chromeos
374