device_settings_service.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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.h"
10#include "base/stl_util.h"
11#include "chrome/browser/chromeos/settings/owner_key_util.h"
12#include "chrome/browser/chromeos/settings/session_manager_operation.h"
13#include "chrome/browser/policy/proto/chromeos/chrome_device_policy.pb.h"
14#include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h"
15#include "chrome/common/chrome_notification_types.h"
16#include "content/public/browser/browser_thread.h"
17#include "content/public/browser/notification_service.h"
18#include "content/public/browser/notification_source.h"
19#include "crypto/rsa_private_key.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      load_retries_left_(kMaxLoadRetries) {
78}
79
80DeviceSettingsService::~DeviceSettingsService() {
81  DCHECK(pending_operations_.empty());
82}
83
84void DeviceSettingsService::SetSessionManager(
85    SessionManagerClient* session_manager_client,
86    scoped_refptr<OwnerKeyUtil> owner_key_util) {
87  DCHECK(session_manager_client);
88  DCHECK(owner_key_util.get());
89  DCHECK(!session_manager_client_);
90  DCHECK(!owner_key_util_.get());
91
92  session_manager_client_ = session_manager_client;
93  owner_key_util_ = owner_key_util;
94
95  session_manager_client_->AddObserver(this);
96
97  StartNextOperation();
98}
99
100void DeviceSettingsService::UnsetSessionManager() {
101  STLDeleteContainerPointers(pending_operations_.begin(),
102                             pending_operations_.end());
103  pending_operations_.clear();
104
105  if (session_manager_client_)
106    session_manager_client_->RemoveObserver(this);
107  session_manager_client_ = NULL;
108  owner_key_util_ = NULL;
109}
110
111scoped_refptr<OwnerKey> DeviceSettingsService::GetOwnerKey() {
112  return owner_key_;
113}
114
115void DeviceSettingsService::Load() {
116  EnqueueLoad(false);
117}
118
119void DeviceSettingsService::SignAndStore(
120    scoped_ptr<em::ChromeDeviceSettingsProto> new_settings,
121    const base::Closure& callback) {
122  Enqueue(
123      new SignAndStoreSettingsOperation(
124          base::Bind(&DeviceSettingsService::HandleCompletedOperation,
125                     weak_factory_.GetWeakPtr(),
126                     callback),
127          new_settings.Pass(),
128          username_));
129}
130
131void DeviceSettingsService::Store(scoped_ptr<em::PolicyFetchResponse> policy,
132                                  const base::Closure& callback) {
133  Enqueue(
134      new StoreSettingsOperation(
135          base::Bind(&DeviceSettingsService::HandleCompletedOperation,
136                     weak_factory_.GetWeakPtr(),
137                     callback),
138          policy.Pass()));
139}
140
141DeviceSettingsService::OwnershipStatus
142    DeviceSettingsService::GetOwnershipStatus() {
143  if (owner_key_.get())
144    return owner_key_->public_key() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE;
145
146  return OWNERSHIP_UNKNOWN;
147}
148
149void DeviceSettingsService::GetOwnershipStatusAsync(
150    const OwnershipStatusCallback& callback) {
151  if (owner_key_.get()) {
152    // If there is a key, report status immediately.
153    base::MessageLoop::current()->PostTask(
154        FROM_HERE,
155        base::Bind(callback,
156                   owner_key_->public_key() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE,
157                   owner_key_->private_key() != NULL));
158  } else {
159    // If the key hasn't been loaded yet, enqueue the callback to be fired when
160    // the next SessionManagerOperation completes. If no operation is pending,
161    // start a load operation to fetch the key and report the result.
162    pending_ownership_status_callbacks_.push_back(callback);
163    if (pending_operations_.empty())
164      EnqueueLoad(false);
165  }
166}
167
168bool DeviceSettingsService::HasPrivateOwnerKey() {
169  return owner_key_.get() && owner_key_->private_key();
170}
171
172void DeviceSettingsService::SetUsername(const std::string& username) {
173  username_ = username;
174
175  // The private key may have become available, so force a key reload.
176  owner_key_ = NULL;
177  EnsureReload(true);
178}
179
180const std::string& DeviceSettingsService::GetUsername() const {
181  return username_;
182}
183
184void DeviceSettingsService::AddObserver(Observer* observer) {
185  observers_.AddObserver(observer);
186}
187
188void DeviceSettingsService::RemoveObserver(Observer* observer) {
189  observers_.RemoveObserver(observer);
190}
191
192void DeviceSettingsService::OwnerKeySet(bool success) {
193  if (!success) {
194    LOG(ERROR) << "Owner key change failed.";
195    return;
196  }
197
198  owner_key_ = NULL;
199  EnsureReload(true);
200}
201
202void DeviceSettingsService::PropertyChangeComplete(bool success) {
203  if (!success) {
204    LOG(ERROR) << "Policy update failed.";
205    return;
206  }
207
208  EnsureReload(false);
209}
210
211void DeviceSettingsService::Enqueue(SessionManagerOperation* operation) {
212  pending_operations_.push_back(operation);
213  if (pending_operations_.front() == operation)
214    StartNextOperation();
215}
216
217void DeviceSettingsService::EnqueueLoad(bool force_key_load) {
218  SessionManagerOperation* operation =
219      new LoadSettingsOperation(
220          base::Bind(&DeviceSettingsService::HandleCompletedOperation,
221                     weak_factory_.GetWeakPtr(),
222                     base::Closure()));
223  operation->set_force_key_load(force_key_load);
224  Enqueue(operation);
225}
226
227void DeviceSettingsService::EnsureReload(bool force_key_load) {
228  if (!pending_operations_.empty())
229    pending_operations_.front()->RestartLoad(force_key_load);
230  else
231    EnqueueLoad(force_key_load);
232}
233
234void DeviceSettingsService::StartNextOperation() {
235  if (!pending_operations_.empty() &&
236      session_manager_client_ &&
237      owner_key_util_.get()) {
238    pending_operations_.front()->Start(session_manager_client_,
239                                       owner_key_util_, owner_key_);
240  }
241}
242
243void DeviceSettingsService::HandleCompletedOperation(
244    const base::Closure& callback,
245    SessionManagerOperation* operation,
246    Status status) {
247  DCHECK_EQ(operation, pending_operations_.front());
248  store_status_ = status;
249
250  OwnershipStatus ownership_status = OWNERSHIP_UNKNOWN;
251  bool is_owner = false;
252  scoped_refptr<OwnerKey> new_key(operation->owner_key());
253  if (new_key.get()) {
254    ownership_status =
255        new_key->public_key() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE;
256    is_owner = (new_key->private_key() != NULL);
257  } else {
258    NOTREACHED() << "Failed to determine key status.";
259  }
260
261  bool new_owner_key = false;
262  if (owner_key_.get() != new_key.get()) {
263    owner_key_ = new_key;
264    new_owner_key = true;
265  }
266
267  if (status == STORE_SUCCESS) {
268    policy_data_ = operation->policy_data().Pass();
269    device_settings_ = operation->device_settings().Pass();
270    load_retries_left_ = kMaxLoadRetries;
271  } else if (status != STORE_KEY_UNAVAILABLE) {
272    LOG(ERROR) << "Session manager operation failed: " << status;
273    // Validation errors can be temprary if the rtc has went on holiday for a
274    // short while. So we will retry such loads for up to 10 minutes.
275    if (status == STORE_TEMP_VALIDATION_ERROR) {
276      if (load_retries_left_ > 0) {
277        load_retries_left_--;
278        LOG(ERROR) << "A re-load has been scheduled due to a validation error.";
279        content::BrowserThread::PostDelayedTask(
280            content::BrowserThread::UI,
281            FROM_HERE,
282            base::Bind(&DeviceSettingsService::Load, base::Unretained(this)),
283            base::TimeDelta::FromMilliseconds(kLoadRetryDelayMs));
284      }
285    }
286  }
287
288  if (new_owner_key) {
289    FOR_EACH_OBSERVER(Observer, observers_, OwnershipStatusChanged());
290    content::NotificationService::current()->Notify(
291        chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED,
292        content::Source<DeviceSettingsService>(this),
293        content::NotificationService::NoDetails());
294  }
295
296  FOR_EACH_OBSERVER(Observer, observers_, DeviceSettingsUpdated());
297
298  std::vector<OwnershipStatusCallback> callbacks;
299  callbacks.swap(pending_ownership_status_callbacks_);
300  for (std::vector<OwnershipStatusCallback>::iterator iter(callbacks.begin());
301       iter != callbacks.end(); ++iter) {
302    iter->Run(ownership_status, is_owner);
303  }
304
305  // The completion callback happens after the notification so clients can
306  // filter self-triggered updates.
307  if (!callback.is_null())
308    callback.Run();
309
310  // Only remove the pending operation here, so new operations triggered by any
311  // of the callbacks above are queued up properly.
312  pending_operations_.pop_front();
313  delete operation;
314
315  StartNextOperation();
316}
317
318ScopedTestDeviceSettingsService::ScopedTestDeviceSettingsService() {
319  DeviceSettingsService::Initialize();
320}
321
322ScopedTestDeviceSettingsService::~ScopedTestDeviceSettingsService() {
323  DeviceSettingsService::Shutdown();
324}
325
326}  // namespace chromeos
327