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

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

Issue 10828032: Add DeviceSettingsService. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase, move to chrome/browser/chromeos/settings. Created 8 years, 4 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/settings/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/settings/owner_key_util.h"
14 #include "chrome/browser/chromeos/settings/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 "chrome/common/chrome_notification_types.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/browser/notification_service.h"
20 #include "content/public/browser/notification_source.h"
21 #include "crypto/rsa_private_key.h"
22
23 namespace em = enterprise_management;
24
25 namespace chromeos {
26
27 static base::LazyInstance<DeviceSettingsService> g_device_settings_service =
Chris Masone 2012/08/03 16:28:25 There was recently a thread about making all these
Mattias Nissler (ping if slow) 2012/08/06 21:28:14 I think you're referring to this thread: https://g
28 LAZY_INSTANCE_INITIALIZER;
29
30 OwnerKey::OwnerKey(scoped_ptr<std::vector<uint8> > public_key,
31 scoped_ptr<crypto::RSAPrivateKey> private_key)
32 : public_key_(public_key.Pass()),
33 private_key_(private_key.Pass()) {}
34
35 OwnerKey::~OwnerKey() {}
36
37 DeviceSettingsService::Observer::~Observer() {}
38
39 DeviceSettingsService::DeviceSettingsService()
40 : session_manager_client_(NULL),
41 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
42 store_status_(STORE_SUCCESS),
43 ownership_status_(OWNERSHIP_UNKNOWN) {}
44
45 DeviceSettingsService::~DeviceSettingsService() {
46 DCHECK(pending_operations_.empty());
47 }
48
49 // static
50 DeviceSettingsService* DeviceSettingsService::Get() {
51 return g_device_settings_service.Pointer();
52 }
53
54 void DeviceSettingsService::Initialize(
55 SessionManagerClient* session_manager_client,
56 scoped_refptr<OwnerKeyUtil> owner_key_util) {
57 DCHECK(session_manager_client);
58 DCHECK(owner_key_util.get());
59 DCHECK(!session_manager_client_);
60 DCHECK(!owner_key_util_.get());
61
62 session_manager_client_ = session_manager_client;
63 owner_key_util_ = owner_key_util;
64
65 session_manager_client_->AddObserver(this);
66
67 StartNextOperation();
68 }
69
70 void DeviceSettingsService::Shutdown() {
71 STLDeleteContainerPointers(pending_operations_.begin(),
72 pending_operations_.end());
73 pending_operations_.clear();
74
75 session_manager_client_->RemoveObserver(this);
76 session_manager_client_ = NULL;
77 owner_key_util_ = NULL;
78 }
79
80 scoped_refptr<OwnerKey> DeviceSettingsService::GetOwnerKey() {
81 return owner_key_;
82 }
83
84 void DeviceSettingsService::Load() {
85 EnqueueLoad(false);
86 }
87
88 void DeviceSettingsService::SignAndStore(
89 scoped_ptr<em::ChromeDeviceSettingsProto> settings,
Chris Masone 2012/08/03 16:28:25 IF this class is holding this settings proto, why
Mattias Nissler (ping if slow) 2012/08/06 21:28:14 It holds the current settings proto. The one passe
90 const base::Closure& callback) {
91 Enqueue(
92 new SignAndStoreSettingsOperation(
93 base::Bind(&DeviceSettingsService::HandleCompletedOperation,
94 weak_factory_.GetWeakPtr(),
95 callback),
96 settings.Pass(),
97 username_));
98 }
99
100 void DeviceSettingsService::Store(const std::string& policy_blob,
101 const base::Closure& callback) {
102 Enqueue(
103 new StoreSettingsOperation(
104 base::Bind(&DeviceSettingsService::HandleCompletedOperation,
105 weak_factory_.GetWeakPtr(),
106 callback),
107 policy_blob));
108 }
109
110 DeviceSettingsService::OwnershipStatus
111 DeviceSettingsService::GetOwnershipStatus(bool blocking) {
112 OwnershipStatus status = OWNERSHIP_UNKNOWN;
113 bool is_owned = false;
114 if (content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
115 ownership_status_lock_.Acquire();
Chris Masone 2012/08/03 16:28:25 I always liked AutoLock() for this stuff. { Aut
Mattias Nissler (ping if slow) 2012/08/06 21:28:14 Done. This function is actually copied legacy code
116 status = ownership_status_;
117 ownership_status_lock_.Release();
118 if (status != OWNERSHIP_UNKNOWN || !blocking)
119 return status;
120 // Under common usage there is very short lapse of time when ownership
121 // status is still unknown after constructing DeviceSettingsService.
122 LOG(ERROR) << "Blocking on UI thread in DeviceSettingsService::GetStatus";
123 base::ThreadRestrictions::ScopedAllowIO allow_io;
124 is_owned = owner_key_util_->IsPublicKeyPresent();
125 } else {
126 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
127 is_owned = owner_key_util_->IsPublicKeyPresent();
128 }
129 status = is_owned ? OWNERSHIP_TAKEN : OWNERSHIP_NONE;
130 SetOwnershipStatus(status);
131 return status;
132 }
133
134 void DeviceSettingsService::GetOwnershipStatusAsync(
Chris Masone 2012/08/03 16:28:25 it seems like the semantics of this and the above
Mattias Nissler (ping if slow) 2012/08/06 21:28:14 True. As commented above, the blocking and locking
135 const OwnershipStatusCallback& callback) {
136 if (owner_key_.get()) {
137 // If there is a key, report status immediately.
138 MessageLoop::current()->PostTask(
139 FROM_HERE,
140 base::Bind(callback,
141 owner_key_->public_key() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE,
142 owner_key_->private_key()));
Chris Masone 2012/08/03 16:28:25 Hm. The level of abstraction between this point o
Mattias Nissler (ping if slow) 2012/08/06 21:28:14 Totally agree. Done.
143 } else {
144 // If the key hasn't been loaded yet, trigger a policy load operation or
145 // wait for an existing operation to finish.
Chris Masone 2012/08/03 16:28:25 Well...you don't wait for an existing operation to
Mattias Nissler (ping if slow) 2012/08/06 21:28:14 Every operation returns the current key status. So
146 pending_ownership_status_callbacks_.push_back(callback);
147 if (pending_operations_.empty())
148 EnqueueLoad(false);
149 }
150 }
151
152 bool DeviceSettingsService::HasPrivateOwnerKey() {
153 return owner_key_.get() && owner_key_->private_key();
154 }
155
156 void DeviceSettingsService::SetUsername(const std::string& username) {
157 username_ = username;
158
159 // The private key may have become available, so force a key reload.
Chris Masone 2012/08/03 16:28:25 How does this follow?
Mattias Nissler (ping if slow) 2012/08/06 21:28:14 We throw away the old key, so the next operation t
160 OwnerKeySet(true);
161 }
162
163 const std::string& DeviceSettingsService::GetUsername() const {
164 return username_;
165 }
166
167 void DeviceSettingsService::AddObserver(Observer* observer) {
168 observers_.AddObserver(observer);
169 }
170
171 void DeviceSettingsService::RemoveObserver(Observer* observer) {
172 observers_.RemoveObserver(observer);
173 }
174
175 void DeviceSettingsService::OwnerKeySet(bool success) {
176 if (!success) {
177 LOG(ERROR) << "Owner key change failed.";
178 return;
179 }
180
181 owner_key_ = NULL;
182 EnsureReload(true);
183 }
184
185 void DeviceSettingsService::PropertyChangeComplete(bool success) {
186 if (!success) {
187 LOG(ERROR) << "Policy update failed.";
188 return;
189 }
190
191 EnsureReload(false);
192 }
193
194 void DeviceSettingsService::Enqueue(SessionManagerOperation* operation) {
195 pending_operations_.push_back(operation);
196 if (pending_operations_.front() == operation)
197 StartNextOperation();
198 }
199
200 void DeviceSettingsService::EnqueueLoad(bool force_key_load) {
201 SessionManagerOperation* operation =
202 new LoadSettingsOperation(
203 base::Bind(&DeviceSettingsService::HandleCompletedOperation,
204 weak_factory_.GetWeakPtr(),
205 base::Closure()));
206 operation->set_force_key_load(force_key_load);
207 Enqueue(operation);
208 }
209
210 void DeviceSettingsService::EnsureReload(bool force_key_load) {
211 if (!pending_operations_.empty())
212 pending_operations_.front()->RestartLoad(force_key_load);
213 else
214 EnqueueLoad(force_key_load);
215 }
216
217 void DeviceSettingsService::StartNextOperation() {
218 if (!pending_operations_.empty() &&
219 session_manager_client_ &&
220 owner_key_util_.get()) {
221 pending_operations_.front()->Start(session_manager_client_,
222 owner_key_util_, owner_key_);
223 }
224 }
225
226 void DeviceSettingsService::HandleCompletedOperation(
227 const base::Closure& callback,
228 SessionManagerOperation* operation,
229 Status status) {
230 DCHECK_EQ(operation, pending_operations_.front());
231 store_status_ = status;
232
233 OwnershipStatus ownership_status = OWNERSHIP_UNKNOWN;
234 bool is_owner = false;
235 scoped_refptr<OwnerKey> new_key(operation->owner_key());
236 if (new_key.get()) {
237 ownership_status =
238 new_key->public_key() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE;
239 is_owner = (new_key->private_key() != NULL);
240 } else {
241 NOTREACHED() << "Failed to determine key status.";
242 }
243 SetOwnershipStatus(ownership_status);
244
245 if (owner_key_.get() != new_key.get()) {
246 owner_key_ = new_key;
247 FOR_EACH_OBSERVER(Observer, observers_, OwnershipStatusChanged());
248 content::NotificationService::current()->Notify(
249 chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED,
250 content::Source<DeviceSettingsService>(this),
251 content::NotificationService::NoDetails());
252 }
253
254 if (status == STORE_SUCCESS) {
255 policy_data_ = operation->policy_data().Pass();
256 device_settings_ = operation->device_settings().Pass();
257 } else if (status != STORE_KEY_UNAVAILABLE) {
258 LOG(ERROR) << "Session manager operation failed: " << status;
259 }
260
261 FOR_EACH_OBSERVER(Observer, observers_, DeviceSettingsUpdated());
262
263 std::vector<OwnershipStatusCallback> callbacks;
264 callbacks.swap(pending_ownership_status_callbacks_);
265 for (std::vector<OwnershipStatusCallback>::iterator iter(callbacks.begin());
266 iter != callbacks.end(); ++iter) {
267 iter->Run(ownership_status, is_owner);
268 }
269
270 // The completion callback happens after the notification so clients can
271 // filter self-triggered updates.
272 if (!callback.is_null())
273 callback.Run();
274
275 // Only remove the pending operation here, so new operations triggered by any
276 // of the callbacks above are queued up properly.
277 pending_operations_.pop_front();
278 delete operation;
279
280 StartNextOperation();
281 }
282
283 void DeviceSettingsService::SetOwnershipStatus(OwnershipStatus new_status) {
284 DCHECK(new_status == OWNERSHIP_TAKEN || new_status == OWNERSHIP_NONE);
285 base::AutoLock lk(ownership_status_lock_);
286 ownership_status_ = new_status;
287 }
288
289 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698