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

Side by Side Diff: chrome/browser/policy/cros_user_policy_cache.cc

Issue 7233006: Store/Retrieve CrOS user policy in session_manager. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 8 years, 8 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/policy/cros_user_policy_cache.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/file_path.h"
13 #include "base/file_util.h"
14 #include "chrome/browser/policy/proto/cloud_policy.pb.h"
15 #include "chrome/browser/policy/proto/device_management_backend.pb.h"
16 #include "chrome/browser/policy/proto/device_management_local.pb.h"
17 #include "chromeos/dbus/session_manager_client.h"
18 #include "content/public/browser/browser_thread.h"
19
20 using content::BrowserThread;
21
22 namespace em = enterprise_management;
23
24 namespace policy {
25
26 // Decodes a CloudPolicySettings object into a policy map. The implementation is
27 // generated code in policy/cloud_policy_generated.cc.
28 void DecodePolicy(const em::CloudPolicySettings& policy,
29 PolicyMap* policies);
30
31 // Takes care of sending a new policy blob to session manager and reports back
32 // the status through a callback.
33 class CrosUserPolicyCache::StorePolicyOperation {
34 public:
35 typedef base::Callback<void(bool)> StatusCallback;
36
37 StorePolicyOperation(
38 const em::PolicyFetchResponse& policy,
39 chromeos::SessionManagerClient* session_manager_client,
40 const StatusCallback& callback);
41
42 // Executes the operation.
43 void Run();
44
45 // Cancels a pending callback.
46 void Cancel();
47
48 const em::PolicyFetchResponse& policy() { return policy_; }
49
50 private:
51 // StorePolicyOperation manages its own lifetime.
52 ~StorePolicyOperation() {}
53
54 // A callback function suitable for passing to session_manager_client.
55 void OnPolicyStored(bool result);
56
57 em::PolicyFetchResponse policy_;
58 chromeos::SessionManagerClient* session_manager_client_;
59 StatusCallback callback_;
60
61 DISALLOW_COPY_AND_ASSIGN(StorePolicyOperation);
62 };
63
64 CrosUserPolicyCache::StorePolicyOperation::StorePolicyOperation(
65 const em::PolicyFetchResponse& policy,
66 chromeos::SessionManagerClient* session_manager_client,
67 const StatusCallback& callback)
68 : policy_(policy),
69 session_manager_client_(session_manager_client),
70 callback_(callback) {}
71
72 void CrosUserPolicyCache::StorePolicyOperation::Run() {
73 std::string serialized;
74 if (!policy_.SerializeToString(&serialized)) {
75 LOG(ERROR) << "Failed to serialize policy protobuf!";
76 callback_.Run(false);
77 delete this;
78 }
79 session_manager_client_->StoreUserPolicy(
80 serialized,
81 base::Bind(&CrosUserPolicyCache::StorePolicyOperation::OnPolicyStored,
82 base::Unretained(this)));
83 }
84
85 void CrosUserPolicyCache::StorePolicyOperation::Cancel() {
86 callback_.Reset();
87 }
88
89 void CrosUserPolicyCache::StorePolicyOperation::OnPolicyStored(bool result) {
90 if (!callback_.is_null())
91 callback_.Run(result);
92 delete this;
93 }
94
95 class CrosUserPolicyCache::RetrievePolicyOperation {
96 public:
97 typedef base::Callback<void(bool, const em::PolicyFetchResponse&)>
98 ResultCallback;
99
100 RetrievePolicyOperation(
101 chromeos::SessionManagerClient* session_manager_client,
102 const ResultCallback& callback);
103
104 // Executes the operation.
105 void Run();
106
107 // Cancels a pending callback.
108 void Cancel();
109
110 private:
111 // RetrievePolicyOperation manages its own lifetime.
112 ~RetrievePolicyOperation() {}
113
114 // Decodes the policy data and triggers a signature check.
115 void OnPolicyRetrieved(const std::string& policy_blob);
116
117 chromeos::SessionManagerClient* session_manager_client_;
118 ResultCallback callback_;
119
120 DISALLOW_COPY_AND_ASSIGN(RetrievePolicyOperation);
121 };
122
123 CrosUserPolicyCache::RetrievePolicyOperation::RetrievePolicyOperation(
124 chromeos::SessionManagerClient* session_manager_client,
125 const ResultCallback& callback)
126 : session_manager_client_(session_manager_client),
127 callback_(callback) {}
128
129 void CrosUserPolicyCache::RetrievePolicyOperation::Run() {
130 session_manager_client_->RetrieveUserPolicy(
131 base::Bind(
132 &CrosUserPolicyCache::RetrievePolicyOperation::OnPolicyRetrieved,
133 base::Unretained(this)));
134 }
135
136 void CrosUserPolicyCache::RetrievePolicyOperation::Cancel() {
137 callback_.Reset();
138 }
139
140 void CrosUserPolicyCache::RetrievePolicyOperation::OnPolicyRetrieved(
141 const std::string& policy_blob) {
142 bool status = true;
143 em::PolicyFetchResponse policy;
144 if (!policy.ParseFromString(policy_blob) ||
145 !policy.has_policy_data() ||
146 !policy.has_policy_data_signature()) {
147 LOG(ERROR) << "Failed to decode policy";
148 status = false;
149 }
150
151 if (!callback_.is_null())
152 callback_.Run(status, policy);
153 delete this;
154 }
155
156 CrosUserPolicyCache::CrosUserPolicyCache(
157 chromeos::SessionManagerClient* session_manager_client,
158 CloudPolicyDataStore* data_store,
159 bool wait_for_policy_fetch,
160 const FilePath& legacy_token_cache_file,
161 const FilePath& legacy_policy_cache_file)
162 : session_manager_client_(session_manager_client),
163 data_store_(data_store),
164 pending_policy_fetch_(wait_for_policy_fetch),
165 pending_disk_cache_load_(true),
166 store_operation_(NULL),
167 retrieve_operation_(NULL),
168 legacy_cache_dir_(legacy_token_cache_file.DirName()),
169 ALLOW_THIS_IN_INITIALIZER_LIST(
170 legacy_token_cache_delegate_factory_(this)),
171 ALLOW_THIS_IN_INITIALIZER_LIST(
172 legacy_policy_cache_delegate_factory_(this)) {
173 DCHECK_EQ(legacy_token_cache_file.DirName().value(),
174 legacy_policy_cache_file.DirName().value());
175
176 legacy_token_loader_ =
177 new UserPolicyTokenLoader(
178 legacy_token_cache_delegate_factory_.GetWeakPtr(),
179 legacy_token_cache_file);
180 legacy_policy_cache_ =
181 new UserPolicyDiskCache(
182 legacy_policy_cache_delegate_factory_.GetWeakPtr(),
183 legacy_policy_cache_file);
184 }
185
186 CrosUserPolicyCache::~CrosUserPolicyCache() {
187 CancelStore();
188 CancelRetrieve();
189 }
190
191 void CrosUserPolicyCache::Load() {
192 retrieve_operation_ =
193 new RetrievePolicyOperation(
194 session_manager_client_,
195 base::Bind(&CrosUserPolicyCache::OnPolicyLoadDone,
196 base::Unretained(this)));
197 retrieve_operation_->Run();
198 }
199
200 bool CrosUserPolicyCache::SetPolicy(const em::PolicyFetchResponse& policy) {
201 CancelStore();
202 set_last_policy_refresh_time(base::Time::NowFromSystemTime());
203 pending_policy_fetch_ = true;
204 store_operation_ =
205 new StorePolicyOperation(policy,
206 session_manager_client_,
207 base::Bind(&CrosUserPolicyCache::OnPolicyStored,
208 base::Unretained(this)));
209 store_operation_->Run();
210 return true;
211 }
212
213 void CrosUserPolicyCache::SetUnmanaged() {
214 base::Time now(base::Time::NowFromSystemTime());
215 SetUnmanagedInternal(now);
216
217 // Construct a policy blob with unmanaged state.
218 em::PolicyData policy_data;
219 policy_data.set_policy_type(data_store_->policy_type());
220 policy_data.set_timestamp((now - base::Time::UnixEpoch()).InMilliseconds());
221 policy_data.set_state(em::PolicyData::UNMANAGED);
222
223 em::PolicyFetchResponse policy;
224 if (!policy_data.SerializeToString(policy.mutable_policy_data())) {
225 LOG(ERROR) << "Failed to serialize policy_data";
226 return;
227 }
228
229 SetPolicy(policy);
230 }
231
232 void CrosUserPolicyCache::SetFetchingDone() {
233 // If there is a pending policy store or reload, wait for that to complete
234 // before reporting fetching done.
235 if (store_operation_ || retrieve_operation_)
236 return;
237
238 pending_policy_fetch_ = false;
239 CheckIfDone();
240 }
241
242 bool CrosUserPolicyCache::DecodePolicyData(const em::PolicyData& policy_data,
243 PolicyMap* policies) {
244 em::CloudPolicySettings policy;
245 if (!policy.ParseFromString(policy_data.policy_value())) {
246 LOG(WARNING) << "Failed to parse CloudPolicySettings protobuf.";
247 return false;
248 }
249 DecodePolicy(policy, policies);
250 return true;
251 }
252
253 void CrosUserPolicyCache::OnTokenLoaded(const std::string& token,
254 const std::string& device_id) {
255 if (token.empty())
256 LOG(WARNING) << "Failed to load legacy token cache";
257
258 data_store_->set_device_id(device_id);
259 data_store_->SetDeviceToken(token, true);
260 }
261
262 void CrosUserPolicyCache::OnDiskCacheLoaded(
263 UserPolicyDiskCache::LoadResult result,
264 const em::CachedCloudPolicyResponse& policy) {
265 if (result == UserPolicyDiskCache::LOAD_RESULT_SUCCESS) {
266 if (policy.unmanaged())
267 SetUnmanagedInternal(base::Time::FromTimeT(policy.timestamp()));
268 else if (policy.has_cloud_policy())
269 InstallLegacyPolicy(policy.cloud_policy());
270 } else {
271 LOG(WARNING) << "Failed to load legacy policy cache: " << result;
272 }
273
274 pending_disk_cache_load_ = false;
275 CheckIfDone();
276 }
277
278 void CrosUserPolicyCache::OnPolicyStored(bool result) {
279 DCHECK(store_operation_);
280 CancelStore();
281 if (result) {
282 // Policy is stored successfully, reload from session_manager and apply.
283 // This helps us making sure we only use policy that session_manager has
284 // checked and confirmed to be good.
285 CancelRetrieve();
286 retrieve_operation_ =
287 new RetrievePolicyOperation(
288 session_manager_client_,
289 base::Bind(&CrosUserPolicyCache::OnPolicyReloadDone,
290 base::Unretained(this)));
291 retrieve_operation_->Run();
292
293 // Now that the new policy blob is installed, remove the old cache dir.
294 if (!legacy_cache_dir_.empty()) {
295 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
296 base::Bind(&RemoveLegacyCacheDir,
297 legacy_cache_dir_));
298 }
299 } else {
300 LOG(ERROR) << "Failed to store user policy.";
301 InformNotifier(CloudPolicySubsystem::LOCAL_ERROR,
302 CloudPolicySubsystem::POLICY_LOCAL_ERROR);
303 pending_policy_fetch_ = false;
304 CheckIfDone();
305 }
306 }
307
308 void CrosUserPolicyCache::OnPolicyLoadDone(
309 bool result,
310 const em::PolicyFetchResponse& policy) {
311 DCHECK(retrieve_operation_);
312 CancelRetrieve();
313 if (!result) {
314 LOG(WARNING) << "No user policy present, trying legacy caches.";
315 legacy_token_loader_->Load();
316 legacy_policy_cache_->Load();
317 return;
318 }
319
320 // We have new-style policy, no need to clean up.
321 legacy_cache_dir_.clear();
322
323 em::PolicyData policy_data;
324 if (!policy_data.ParseFromString(policy.policy_data())) {
325 LOG(WARNING) << "Failed to parse PolicyData protobuf.";
326 InformNotifier(CloudPolicySubsystem::LOCAL_ERROR,
327 CloudPolicySubsystem::POLICY_LOCAL_ERROR);
328 data_store_->SetDeviceToken(std::string(), true);
329 } else if (policy_data.request_token().empty() ||
330 policy_data.username().empty() ||
331 policy_data.device_id().empty()) {
332 LOG(WARNING) << "Policy protobuf is missing credentials";
333 InformNotifier(CloudPolicySubsystem::LOCAL_ERROR,
334 CloudPolicySubsystem::POLICY_LOCAL_ERROR);
335 data_store_->SetDeviceToken(std::string(), true);
336 } else {
337 data_store_->set_device_id(policy_data.device_id());
338 data_store_->SetDeviceToken(policy_data.request_token(), true);
339 if (SetPolicyInternal(policy, NULL, true))
340 set_last_policy_refresh_time(base::Time::NowFromSystemTime());
341 }
342
343 pending_disk_cache_load_ = false;
344 CheckIfDone();
345 }
346
347 void CrosUserPolicyCache::OnPolicyReloadDone(
348 bool result,
349 const em::PolicyFetchResponse& policy) {
350 DCHECK(retrieve_operation_);
351 CancelRetrieve();
352 if (result) {
353 if (SetPolicyInternal(policy, NULL, false))
354 set_last_policy_refresh_time(base::Time::NowFromSystemTime());
355 } else {
356 InformNotifier(CloudPolicySubsystem::LOCAL_ERROR,
357 CloudPolicySubsystem::POLICY_LOCAL_ERROR);
358 }
359 pending_policy_fetch_ = false;
360 CheckIfDone();
361 }
362
363 void CrosUserPolicyCache::CancelStore() {
364 if (store_operation_) {
365 store_operation_->Cancel();
366 store_operation_ = NULL;
367 }
368 }
369
370 void CrosUserPolicyCache::CancelRetrieve() {
371 if (retrieve_operation_) {
372 retrieve_operation_->Cancel();
373 retrieve_operation_ = NULL;
374 }
375 }
376
377 void CrosUserPolicyCache::CheckIfDone() {
378 if (!pending_policy_fetch_ && !pending_disk_cache_load_) {
379 if (!IsReady())
380 SetReady();
381 CloudPolicyCacheBase::SetFetchingDone();
382 }
383 }
384
385 void CrosUserPolicyCache::InstallLegacyPolicy(
386 const em::PolicyFetchResponse& policy) {
387 em::PolicyFetchResponse mutable_policy(policy);
388 mutable_policy.clear_policy_data_signature();
389 mutable_policy.clear_new_public_key();
390 mutable_policy.clear_new_public_key_signature();
391 em::PolicyData policy_data;
392 if (!policy_data.ParseFromString(mutable_policy.policy_data())) {
393 LOG(ERROR) << "Failed to parse policy data.";
394 return;
395 }
396
397 policy_data.clear_public_key_version();
398 if (!policy_data.SerializeToString(mutable_policy.mutable_policy_data())) {
399 LOG(ERROR) << "Failed to serialize policy data.";
400 return;
401 }
402
403 base::Time timestamp;
404 if (SetPolicyInternal(mutable_policy, &timestamp, true))
405 set_last_policy_refresh_time(timestamp);
406 }
407
408 // static
409 void CrosUserPolicyCache::RemoveLegacyCacheDir(const FilePath& dir) {
410 if (!file_util::Delete(dir, true))
411 PLOG(ERROR) << "Failed to remove " << dir.value();
412 }
413
414 } // namespace policy
OLDNEW
« no previous file with comments | « chrome/browser/policy/cros_user_policy_cache.h ('k') | chrome/browser/policy/cros_user_policy_cache_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698