Upstream version 10.39.225.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 "base/time/time.h"
12 #include "chrome/browser/chrome_notification_types.h"
13 #include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
14 #include "chrome/browser/chromeos/settings/session_manager_operation.h"
15 #include "components/ownership/owner_key_util.h"
16 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "content/public/browser/notification_service.h"
19 #include "content/public/browser/notification_source.h"
20 #include "crypto/rsa_private_key.h"
21
22 namespace em = enterprise_management;
23
24 using ownership::OwnerKeyUtil;
25 using ownership::PublicKey;
26
27 namespace {
28
29 // Delay between load retries when there was a validation error.
30 // NOTE: This code is here to mitigate clock loss on some devices where policy
31 // loads will fail with a validation error caused by RTC clock being reset when
32 // the battery is drained.
33 int kLoadRetryDelayMs = 1000 * 5;
34 // Maximal number of retries before we give up. Calculated to allow for 10 min
35 // of retry time.
36 int kMaxLoadRetries = (1000 * 60 * 10) / kLoadRetryDelayMs;
37
38 // Assembles PolicyData based on |settings|, |policy_data| and
39 // |user_id|.
40 scoped_ptr<em::PolicyData> AssemblePolicy(
41     const std::string& user_id,
42     const em::PolicyData* policy_data,
43     const em::ChromeDeviceSettingsProto* settings) {
44   scoped_ptr<em::PolicyData> policy(new em::PolicyData());
45   if (policy_data) {
46     // Preserve management settings.
47     if (policy_data->has_management_mode())
48       policy->set_management_mode(policy_data->management_mode());
49     if (policy_data->has_request_token())
50       policy->set_request_token(policy_data->request_token());
51     if (policy_data->has_device_id())
52       policy->set_device_id(policy_data->device_id());
53   } else {
54     // If there's no previous policy data, this is the first time the device
55     // setting is set. We set the management mode to NOT_MANAGED initially.
56     policy->set_management_mode(em::PolicyData::NOT_MANAGED);
57   }
58   policy->set_policy_type(policy::dm_protocol::kChromeDevicePolicyType);
59   policy->set_timestamp(
60       (base::Time::Now() - base::Time::UnixEpoch()).InMilliseconds());
61   policy->set_username(user_id);
62   if (!settings->SerializeToString(policy->mutable_policy_value()))
63     return scoped_ptr<em::PolicyData>();
64
65   return policy.Pass();
66 }
67
68 // Returns true if it is okay to transfer from the current mode to the new
69 // mode. This function should be called in SetManagementMode().
70 bool CheckManagementModeTransition(em::PolicyData::ManagementMode current_mode,
71                                    em::PolicyData::ManagementMode new_mode) {
72   // Mode is not changed.
73   if (current_mode == new_mode)
74     return true;
75
76   switch (current_mode) {
77     case em::PolicyData::NOT_MANAGED:
78       // For consumer management enrollment.
79       return new_mode == em::PolicyData::CONSUMER_MANAGED;
80
81     case em::PolicyData::ENTERPRISE_MANAGED:
82       // Management mode cannot be set when it is currently ENTERPRISE_MANAGED.
83       return false;
84
85     case em::PolicyData::CONSUMER_MANAGED:
86       // For consumer management unenrollment.
87       return new_mode == em::PolicyData::NOT_MANAGED;
88   }
89
90   NOTREACHED();
91   return false;
92 }
93
94 }  // namespace
95
96 namespace chromeos {
97
98 DeviceSettingsService::Observer::~Observer() {}
99
100 static DeviceSettingsService* g_device_settings_service = NULL;
101
102 // static
103 void DeviceSettingsService::Initialize() {
104   CHECK(!g_device_settings_service);
105   g_device_settings_service = new DeviceSettingsService();
106 }
107
108 // static
109 bool DeviceSettingsService::IsInitialized() {
110   return g_device_settings_service;
111 }
112
113 // static
114 void DeviceSettingsService::Shutdown() {
115   DCHECK(g_device_settings_service);
116   delete g_device_settings_service;
117   g_device_settings_service = NULL;
118 }
119
120 // static
121 DeviceSettingsService* DeviceSettingsService::Get() {
122   CHECK(g_device_settings_service);
123   return g_device_settings_service;
124 }
125
126 DeviceSettingsService::DeviceSettingsService()
127     : session_manager_client_(NULL),
128       store_status_(STORE_SUCCESS),
129       load_retries_left_(kMaxLoadRetries),
130       weak_factory_(this) {
131 }
132
133 DeviceSettingsService::~DeviceSettingsService() {
134   DCHECK(pending_operations_.empty());
135 }
136
137 void DeviceSettingsService::SetSessionManager(
138     SessionManagerClient* session_manager_client,
139     scoped_refptr<OwnerKeyUtil> owner_key_util) {
140   DCHECK(session_manager_client);
141   DCHECK(owner_key_util.get());
142   DCHECK(!session_manager_client_);
143   DCHECK(!owner_key_util_.get());
144
145   session_manager_client_ = session_manager_client;
146   owner_key_util_ = owner_key_util;
147
148   session_manager_client_->AddObserver(this);
149
150   StartNextOperation();
151 }
152
153 void DeviceSettingsService::UnsetSessionManager() {
154   STLDeleteContainerPointers(pending_operations_.begin(),
155                              pending_operations_.end());
156   pending_operations_.clear();
157
158   if (session_manager_client_)
159     session_manager_client_->RemoveObserver(this);
160   session_manager_client_ = NULL;
161   owner_key_util_ = NULL;
162 }
163
164 scoped_refptr<PublicKey> DeviceSettingsService::GetPublicKey() {
165   return public_key_;
166 }
167
168 void DeviceSettingsService::Load() {
169   EnqueueLoad(false);
170 }
171
172 void DeviceSettingsService::SignAndStore(
173     scoped_ptr<em::ChromeDeviceSettingsProto> new_settings,
174     const base::Closure& callback) {
175   if (!owner_settings_service_) {
176     HandleError(STORE_KEY_UNAVAILABLE, callback);
177     return;
178   }
179   scoped_ptr<em::PolicyData> policy =
180       AssemblePolicy(GetUsername(), policy_data(), new_settings.get());
181   if (!policy) {
182     HandleError(STORE_POLICY_ERROR, callback);
183     return;
184   }
185
186   owner_settings_service_->SignAndStorePolicyAsync(policy.Pass(), callback);
187 }
188
189 void DeviceSettingsService::SetManagementSettings(
190     em::PolicyData::ManagementMode management_mode,
191     const std::string& request_token,
192     const std::string& device_id,
193     const base::Closure& callback) {
194   if (!owner_settings_service_) {
195     HandleError(STORE_KEY_UNAVAILABLE, callback);
196     return;
197   }
198
199   em::PolicyData::ManagementMode current_mode = em::PolicyData::NOT_MANAGED;
200   if (policy_data() && policy_data()->has_management_mode())
201     current_mode = policy_data()->management_mode();
202
203   if (!CheckManagementModeTransition(current_mode, management_mode)) {
204     LOG(ERROR) << "Invalid management mode transition: current mode = "
205                << current_mode << ", new mode = " << management_mode;
206     HandleError(DeviceSettingsService::STORE_POLICY_ERROR, callback);
207     return;
208   }
209
210   scoped_ptr<em::PolicyData> policy =
211       AssemblePolicy(GetUsername(), policy_data(), device_settings());
212   if (!policy) {
213     HandleError(DeviceSettingsService::STORE_POLICY_ERROR, callback);
214     return;
215   }
216
217   policy->set_management_mode(management_mode);
218   policy->set_request_token(request_token);
219   policy->set_device_id(device_id);
220
221   owner_settings_service_->SignAndStorePolicyAsync(policy.Pass(), callback);
222 }
223
224 void DeviceSettingsService::Store(scoped_ptr<em::PolicyFetchResponse> policy,
225                                   const base::Closure& callback) {
226   Enqueue(
227       new StoreSettingsOperation(
228           base::Bind(&DeviceSettingsService::HandleCompletedOperation,
229                      weak_factory_.GetWeakPtr(),
230                      callback),
231           policy.Pass()));
232 }
233
234 DeviceSettingsService::OwnershipStatus
235     DeviceSettingsService::GetOwnershipStatus() {
236   if (public_key_.get())
237     return public_key_->is_loaded() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE;
238   return OWNERSHIP_UNKNOWN;
239 }
240
241 void DeviceSettingsService::GetOwnershipStatusAsync(
242     const OwnershipStatusCallback& callback) {
243   if (public_key_.get()) {
244     // If there is a key, report status immediately.
245     base::MessageLoop::current()->PostTask(
246         FROM_HERE, base::Bind(callback, GetOwnershipStatus()));
247   } else {
248     // If the key hasn't been loaded yet, enqueue the callback to be fired when
249     // the next SessionManagerOperation completes. If no operation is pending,
250     // start a load operation to fetch the key and report the result.
251     pending_ownership_status_callbacks_.push_back(callback);
252     if (pending_operations_.empty())
253       EnqueueLoad(false);
254   }
255 }
256
257 bool DeviceSettingsService::HasPrivateOwnerKey() {
258   return owner_settings_service_ && owner_settings_service_->IsOwner();
259 }
260
261 void DeviceSettingsService::InitOwner(
262     const std::string& username,
263     const base::WeakPtr<ownership::OwnerSettingsService>&
264         owner_settings_service) {
265   // When InitOwner() is called twice with the same |username| it's
266   // worth to reload settings since owner key may become available.
267   if (!username_.empty() && username_ != username)
268     return;
269   username_ = username;
270   owner_settings_service_ = owner_settings_service;
271
272   EnsureReload(true);
273 }
274
275 const std::string& DeviceSettingsService::GetUsername() const {
276   return username_;
277 }
278
279 void DeviceSettingsService::AddObserver(Observer* observer) {
280   observers_.AddObserver(observer);
281 }
282
283 void DeviceSettingsService::RemoveObserver(Observer* observer) {
284   observers_.RemoveObserver(observer);
285 }
286
287 void DeviceSettingsService::OwnerKeySet(bool success) {
288   if (!success) {
289     LOG(ERROR) << "Owner key change failed.";
290     return;
291   }
292
293   public_key_ = NULL;
294   EnsureReload(true);
295 }
296
297 void DeviceSettingsService::PropertyChangeComplete(bool success) {
298   if (!success) {
299     LOG(ERROR) << "Policy update failed.";
300     return;
301   }
302
303   EnsureReload(false);
304 }
305
306 void DeviceSettingsService::Enqueue(SessionManagerOperation* operation) {
307   pending_operations_.push_back(operation);
308   if (pending_operations_.front() == operation)
309     StartNextOperation();
310 }
311
312 void DeviceSettingsService::EnqueueLoad(bool force_key_load) {
313   SessionManagerOperation* operation =
314       new LoadSettingsOperation(
315           base::Bind(&DeviceSettingsService::HandleCompletedOperation,
316                      weak_factory_.GetWeakPtr(),
317                      base::Closure()));
318   operation->set_force_key_load(force_key_load);
319   operation->set_username(username_);
320   operation->set_owner_settings_service(owner_settings_service_);
321   Enqueue(operation);
322 }
323
324 void DeviceSettingsService::EnsureReload(bool force_key_load) {
325   if (!pending_operations_.empty()) {
326     pending_operations_.front()->set_username(username_);
327     pending_operations_.front()->set_owner_settings_service(
328         owner_settings_service_);
329     pending_operations_.front()->RestartLoad(force_key_load);
330   } else {
331     EnqueueLoad(force_key_load);
332   }
333 }
334
335 void DeviceSettingsService::StartNextOperation() {
336   if (!pending_operations_.empty() &&
337       session_manager_client_ &&
338       owner_key_util_.get()) {
339     pending_operations_.front()->Start(
340         session_manager_client_, owner_key_util_, public_key_);
341   }
342 }
343
344 void DeviceSettingsService::HandleCompletedOperation(
345     const base::Closure& callback,
346     SessionManagerOperation* operation,
347     Status status) {
348   DCHECK_EQ(operation, pending_operations_.front());
349   store_status_ = status;
350
351   OwnershipStatus ownership_status = OWNERSHIP_UNKNOWN;
352   scoped_refptr<PublicKey> new_key(operation->public_key());
353   if (new_key.get()) {
354     ownership_status = new_key->is_loaded() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE;
355   } else {
356     NOTREACHED() << "Failed to determine key status.";
357   }
358
359   bool new_owner_key = false;
360   if (public_key_.get() != new_key.get()) {
361     public_key_ = new_key;
362     new_owner_key = true;
363   }
364
365   if (status == STORE_SUCCESS) {
366     policy_data_ = operation->policy_data().Pass();
367     device_settings_ = operation->device_settings().Pass();
368     load_retries_left_ = kMaxLoadRetries;
369   } else if (status != STORE_KEY_UNAVAILABLE) {
370     LOG(ERROR) << "Session manager operation failed: " << status;
371     // Validation errors can be temporary if the rtc has gone on holiday for a
372     // short while. So we will retry such loads for up to 10 minutes.
373     if (status == STORE_TEMP_VALIDATION_ERROR) {
374       if (load_retries_left_ > 0) {
375         load_retries_left_--;
376         LOG(ERROR) << "A re-load has been scheduled due to a validation error.";
377         content::BrowserThread::PostDelayedTask(
378             content::BrowserThread::UI,
379             FROM_HERE,
380             base::Bind(&DeviceSettingsService::Load, base::Unretained(this)),
381             base::TimeDelta::FromMilliseconds(kLoadRetryDelayMs));
382       } else {
383         // Once we've given up retrying, the validation error is not temporary
384         // anymore.
385         store_status_ = STORE_VALIDATION_ERROR;
386       }
387     }
388   }
389
390   if (new_owner_key) {
391     FOR_EACH_OBSERVER(Observer, observers_, OwnershipStatusChanged());
392     content::NotificationService::current()->Notify(
393         chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED,
394         content::Source<DeviceSettingsService>(this),
395         content::NotificationService::NoDetails());
396   }
397
398   FOR_EACH_OBSERVER(Observer, observers_, DeviceSettingsUpdated());
399
400   std::vector<OwnershipStatusCallback> callbacks;
401   callbacks.swap(pending_ownership_status_callbacks_);
402   for (std::vector<OwnershipStatusCallback>::iterator iter(callbacks.begin());
403        iter != callbacks.end(); ++iter) {
404     iter->Run(ownership_status);
405   }
406
407   // The completion callback happens after the notification so clients can
408   // filter self-triggered updates.
409   if (!callback.is_null())
410     callback.Run();
411
412   // Only remove the pending operation here, so new operations triggered by any
413   // of the callbacks above are queued up properly.
414   pending_operations_.pop_front();
415   delete operation;
416
417   StartNextOperation();
418 }
419
420 void DeviceSettingsService::HandleError(Status status,
421                                         const base::Closure& callback) {
422   store_status_ = status;
423
424   LOG(ERROR) << "Session manager operation failed: " << status;
425
426   FOR_EACH_OBSERVER(Observer, observers_, DeviceSettingsUpdated());
427
428   // The completion callback happens after the notification so clients can
429   // filter self-triggered updates.
430   if (!callback.is_null())
431     callback.Run();
432 }
433
434 void DeviceSettingsService::OnSignAndStoreOperationCompleted(Status status) {
435   store_status_ = status;
436   FOR_EACH_OBSERVER(Observer, observers_, DeviceSettingsUpdated());
437 }
438
439 ScopedTestDeviceSettingsService::ScopedTestDeviceSettingsService() {
440   DeviceSettingsService::Initialize();
441 }
442
443 ScopedTestDeviceSettingsService::~ScopedTestDeviceSettingsService() {
444   // Clean pending operations.
445   DeviceSettingsService::Get()->UnsetSessionManager();
446   DeviceSettingsService::Shutdown();
447 }
448
449 }  // namespace chromeos