device_settings_service.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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      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
86DeviceSettingsService::~DeviceSettingsService() {
87  DCHECK(pending_operations_.empty());
88  if (TPMTokenLoader::IsInitialized())
89    TPMTokenLoader::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_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
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::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
246void DeviceSettingsService::Enqueue(SessionManagerOperation* operation) {
247  pending_operations_.push_back(operation);
248  if (pending_operations_.front() == operation)
249    StartNextOperation();
250}
251
252void 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
262void 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
269void 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
278void 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
364ScopedTestDeviceSettingsService::ScopedTestDeviceSettingsService() {
365  DeviceSettingsService::Initialize();
366}
367
368ScopedTestDeviceSettingsService::~ScopedTestDeviceSettingsService() {
369  // Clean pending operations.
370  DeviceSettingsService::Get()->UnsetSessionManager();
371  DeviceSettingsService::Shutdown();
372}
373
374}  // namespace chromeos
375