Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(98)

Side by Side Diff: chrome/browser/chromeos/login/device_settings_service.cc

Issue 10828032: Add DeviceSettingsService. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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/login/device_settings_service.h"
6
7 #include "base/bind.h"
8 #include "base/file_util.h"
9 #include "base/lazy_instance.h"
10 #include "base/logging.h"
11 #include "base/message_loop.h"
12 #include "base/stl_util.h"
13 #include "chrome/browser/chromeos/login/owner_key_util.h"
14 #include "chrome/browser/chromeos/login/session_manager_operation.h"
15 #include "chrome/browser/policy/proto/chrome_device_policy.pb.h"
16 #include "chrome/browser/policy/proto/device_management_backend.pb.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "crypto/rsa_private_key.h"
19
20 namespace em = enterprise_management;
21
22 namespace chromeos {
23
24 static base::LazyInstance<DeviceSettingsService> g_device_settings_service =
25 LAZY_INSTANCE_INITIALIZER;
26
27 OwnerKey::OwnerKey(scoped_ptr<std::vector<uint8> > public_key,
28 scoped_ptr<crypto::RSAPrivateKey> private_key)
29 : public_key_(public_key.Pass()),
30 private_key_(private_key.Pass()) {}
31
32 OwnerKey::~OwnerKey() {}
33
34 DeviceSettingsService::Observer::~Observer() {}
35
36 DeviceSettingsService::DeviceSettingsService()
37 : session_manager_client_(NULL),
38 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
39 store_status_(STORE_SUCCESS),
40 ownership_status_(OWNERSHIP_UNKNOWN) {}
41
42 DeviceSettingsService::~DeviceSettingsService() {
43 STLDeleteContainerPointers(pending_operations_.begin(),
44 pending_operations_.end());
45 }
46
47 // static
48 DeviceSettingsService* DeviceSettingsService::Get() {
49 return g_device_settings_service.Pointer();
50 }
51
52 void DeviceSettingsService::Initialize(
53 SessionManagerClient* session_manager_client,
54 scoped_refptr<OwnerKeyUtil> owner_key_util) {
55 DCHECK(!session_manager_client_);
56 DCHECK(!owner_key_util_.get());
57
58 session_manager_client_ = session_manager_client;
59 owner_key_util_ = owner_key_util;
60
61 session_manager_client_->AddObserver(this);
62
63 RunNextOperation();
64 }
65
66 void DeviceSettingsService::Shutdown() {
67 session_manager_client_->RemoveObserver(this);
68 session_manager_client_ = NULL;
69 owner_key_util_ = NULL;
70 }
71
72 scoped_refptr<OwnerKey> DeviceSettingsService::GetOwnerKey() {
73 return owner_key_;
74 }
75
76 void DeviceSettingsService::Load() {
77 EnqueueLoad(false);
78 }
79
80 void DeviceSettingsService::SignAndStore(
81 scoped_ptr<em::ChromeDeviceSettingsProto> settings,
82 const base::Closure& callback) {
83 Enqueue(
84 new SignAndStoreSettingsOperation(
85 owner_key_util_,
86 base::Bind(&DeviceSettingsService::HandleCompletedOperation,
87 weak_factory_.GetWeakPtr(),
88 callback),
89 settings.Pass(),
90 username_));
91 }
92
93 void DeviceSettingsService::Store(const std::string& policy_blob,
94 const base::Closure& callback) {
95 Enqueue(
96 new StoreSettingsOperation(
97 owner_key_util_,
98 base::Bind(&DeviceSettingsService::HandleCompletedOperation,
99 weak_factory_.GetWeakPtr(),
100 callback),
101 policy_blob));
102 }
103
104 DeviceSettingsService::OwnershipStatus
105 DeviceSettingsService::GetOwnershipStatus(bool blocking) {
106 OwnershipStatus status = OWNERSHIP_UNKNOWN;
107 bool is_owned = false;
108 if (content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
109 ownership_status_lock_.Acquire();
110 status = ownership_status_;
111 ownership_status_lock_.Release();
112 if (status != OWNERSHIP_UNKNOWN || !blocking)
113 return status;
114 // Under common usage there is very short lapse of time when ownership
115 // status is still unknown after constructing DeviceSettingsService.
116 LOG(ERROR) << "Blocking on UI thread in DeviceSettingsService::GetStatus";
117 base::ThreadRestrictions::ScopedAllowIO allow_io;
118 is_owned = owner_key_util_->IsPublicKeyPresent();
119 } else {
120 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
121 is_owned = owner_key_util_->IsPublicKeyPresent();
122 }
123 status = is_owned ? OWNERSHIP_TAKEN : OWNERSHIP_NONE;
124 SetOwnershipStatus(status);
125 return status;
126 }
127
128 void DeviceSettingsService::GetOwnershipStatusAsync(
129 const OwnershipStatusCallback& callback) {
130 if (owner_key_.get()) {
131 // If there is a key, report status immediately.
132 MessageLoop::current()->PostTask(
133 FROM_HERE,
134 base::Bind(callback,
135 owner_key_->public_key() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE,
136 owner_key_->private_key()));
137 } else {
138 // If the key hasn't been loaded yet, trigger a policy load operation or
139 // wait for an existing operation to finish.
140 pending_ownership_status_callbacks_.push_back(callback);
141 if (pending_operations_.empty());
142 EnqueueLoad(false);
143 }
144 }
145
146 bool DeviceSettingsService::HasPrivateOwnerKey() {
147 return owner_key_.get() && owner_key_->private_key();
148 }
149
150 void DeviceSettingsService::SetUsername(const std::string& username) {
151 username_ = username;
152
153 // The private key may have become available, so force a key reload.
154 OwnerKeySet(true);
155 }
156
157 const std::string& DeviceSettingsService::GetUsername() const {
158 return username_;
159 }
160
161 void DeviceSettingsService::AddObserver(Observer* observer) {
162 observers_.AddObserver(observer);
163 }
164
165 void DeviceSettingsService::RemoveObserver(Observer* observer) {
166 observers_.RemoveObserver(observer);
167 }
168
169 void DeviceSettingsService::OwnerKeySet(bool success) {
170 if (!success) {
171 LOG(ERROR) << "Owner key change failed.";
172 return;
173 }
174
175 owner_key_ = NULL;
176 EnsureReload(true);
177 }
178
179 void DeviceSettingsService::PropertyChangeComplete(bool success) {
180 if (!success) {
181 LOG(ERROR) << "Policy update failed.";
182 return;
183 }
184
185 EnsureReload(false);
186 }
187
188 void DeviceSettingsService::Enqueue(SessionManagerOperation* operation) {
189 pending_operations_.push_back(operation);
190 if (pending_operations_.front() == operation)
191 RunNextOperation();
192 }
193
194 void DeviceSettingsService::EnqueueLoad(bool force_key_load) {
195 SessionManagerOperation* operation =
196 new LoadSettingsOperation(
197 owner_key_util_,
198 base::Bind(&DeviceSettingsService::HandleCompletedOperation,
199 weak_factory_.GetWeakPtr(),
200 base::Closure()));
201 operation->set_force_key_load(force_key_load);
202 Enqueue(operation);
203 }
204
205 void DeviceSettingsService::EnsureReload(bool force_key_load) {
206 if (!pending_operations_.empty())
207 pending_operations_.front()->RestartLoad(force_key_load);
208 else
209 EnqueueLoad(force_key_load);
210 }
211
212 void DeviceSettingsService::RunNextOperation() {
213 if (!pending_operations_.empty() && session_manager_client_) {
214 pending_operations_.front()->set_owner_key(owner_key_);
215 pending_operations_.front()->set_session_manager_client(
216 session_manager_client_);
217 pending_operations_.front()->Run();
218 }
219 }
220
221 void DeviceSettingsService::HandleCompletedOperation(
222 const base::Closure& callback,
223 SessionManagerOperation* operation,
224 Status status) {
225 DCHECK_EQ(operation, pending_operations_.front());
226 store_status_ = status;
227
228 OwnershipStatus ownership_status = OWNERSHIP_UNKNOWN;
229 bool is_owner = false;
230 scoped_refptr<OwnerKey> new_key(operation->owner_key());
231 if (new_key.get()) {
232 ownership_status =
233 new_key->public_key() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE;
234 is_owner = new_key->private_key();
235 } else {
236 NOTREACHED() << "Failed to determine key status.";
237 }
238 SetOwnershipStatus(ownership_status);
239
240 if (owner_key_.get() != new_key.get()) {
241 owner_key_ = new_key;
242 FOR_EACH_OBSERVER(Observer, observers_, OwnershipStatusChanged());
243 }
244
245 if (status == STORE_SUCCESS) {
246 policy_data_ = operation->policy_data().Pass();
247 device_settings_ = operation->device_settings().Pass();
248 } else if (status != STORE_KEY_UNAVAILABLE) {
249 LOG(ERROR) << "Session manager operation failed: " << status;
250 }
251
252 FOR_EACH_OBSERVER(Observer, observers_, DeviceSettingsUpdated());
253
254 std::vector<OwnershipStatusCallback> callbacks;
255 callbacks.swap(pending_ownership_status_callbacks_);
256 for (std::vector<OwnershipStatusCallback>::iterator iter(callbacks.begin());
257 iter != callbacks.end(); ++iter) {
258 iter->Run(ownership_status, is_owner);
259 }
260
261 // The completion callback happens after the notification so clients can
262 // filter self-triggered updates.
263 if (!callback.is_null())
264 callback.Run();
265
266 // Only remove the pending operation here, so new operations triggered by any
267 // of the callbacks above are queued up properly.
268 pending_operations_.pop_front();
269 delete operation;
270
271 RunNextOperation();
272 }
273
274 void DeviceSettingsService::SetOwnershipStatus(OwnershipStatus new_status) {
275 DCHECK(new_status == OWNERSHIP_TAKEN || new_status == OWNERSHIP_NONE);
276 base::AutoLock lk(ownership_status_lock_);
277 ownership_status_ = new_status;
278 }
279
280 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698