Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2011 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 "base/path_service.h" | |
| 15 #include "chrome/browser/chromeos/cros/login_library.h" | |
| 16 #include "chrome/browser/policy/proto/cloud_policy.pb.h" | |
| 17 #include "chrome/browser/policy/proto/device_management_backend.pb.h" | |
| 18 #include "chrome/browser/policy/proto/device_management_local.pb.h" | |
| 19 #include "chrome/common/chrome_paths.h" | |
| 20 #include "chrome/common/extensions/extension_constants.h" | |
| 21 #include "content/browser/browser_thread.h" | |
| 22 #include "crypto/signature_verifier.h" | |
| 23 | |
| 24 using extension_misc::kSignatureAlgorithm; | |
| 25 | |
| 26 static const FilePath::CharType kUserPolicyKeyFile[] = FILE_PATH_LITERAL("key"); | |
| 27 | |
| 28 namespace policy { | |
| 29 | |
| 30 // Decodes a CloudPolicySettings object into two maps with mandatory and | |
| 31 // recommended settings, respectively. The implementation is generated code | |
| 32 // in policy/cloud_policy_generated.cc. | |
| 33 void DecodePolicy(const em::CloudPolicySettings& policy, | |
| 34 PolicyMap* mandatory, PolicyMap* recommended); | |
| 35 | |
| 36 // Manages the policy key and implements signature checking on the key. | |
| 37 class CrosUserPolicyCache::PolicyKey | |
| 38 : public base::RefCountedThreadSafe<PolicyKey> { | |
| 39 public: | |
| 40 typedef base::Callback<void(bool)> StatusCallback; | |
| 41 | |
| 42 explicit PolicyKey(const FilePath& key_file); | |
| 43 | |
| 44 // Loads the key asynchronously on the file thread. | |
| 45 void LoadKey(); | |
| 46 | |
| 47 // Checks whether |signature| is a valid over |data|. The status will be | |
| 48 // reported through |callback| once the check is complete. If the |reload_key| | |
| 49 // flag is set, the key is first reloaded from the file. | |
| 50 void CheckSignature(const std::string& data, | |
| 51 const std::string& signature, | |
| 52 bool reload_key, | |
| 53 const StatusCallback& callback); | |
| 54 | |
| 55 private: | |
| 56 // Reports the result of a signature check. Must be called on the UI thread. | |
| 57 void ReportResult(const StatusCallback& callback, bool result); | |
| 58 | |
| 59 // Read the public key from |key_file_|. Must be called on the file thread. | |
| 60 void ReadKeyFromFile(); | |
| 61 | |
| 62 // Runs the actual signature checking. Must be called on the file thread. | |
| 63 void CheckSignatureOnFileThread(const std::string& data, | |
| 64 const std::string& signature, | |
| 65 bool reload_key, | |
| 66 const StatusCallback& callback); | |
| 67 | |
| 68 // The data members should only be accessed from the file thread. | |
| 69 const FilePath key_file_; | |
| 70 std::vector<uint8> public_key_; | |
| 71 | |
| 72 DISALLOW_COPY_AND_ASSIGN(PolicyKey); | |
| 73 }; | |
| 74 | |
| 75 CrosUserPolicyCache::PolicyKey::PolicyKey(const FilePath& key_file) | |
| 76 : key_file_(key_file) {} | |
| 77 | |
| 78 void CrosUserPolicyCache::PolicyKey::LoadKey() { | |
| 79 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | |
| 80 NewRunnableMethod(this, &PolicyKey::ReadKeyFromFile)); | |
| 81 } | |
| 82 | |
| 83 void CrosUserPolicyCache::PolicyKey::CheckSignature( | |
| 84 const std::string& data, | |
| 85 const std::string& signature, | |
| 86 bool reload_key, | |
| 87 const StatusCallback& callback) { | |
| 88 BrowserThread::PostTask( | |
| 89 BrowserThread::FILE, FROM_HERE, | |
| 90 NewRunnableMethod(this, &PolicyKey::CheckSignatureOnFileThread, | |
| 91 data, signature, reload_key, callback)); | |
| 92 } | |
| 93 | |
| 94 void CrosUserPolicyCache::PolicyKey::CheckSignatureOnFileThread( | |
| 95 const std::string& data, | |
| 96 const std::string& signature, | |
| 97 bool reload_key, | |
| 98 const StatusCallback& callback) { | |
| 99 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
| 100 bool status = false; | |
| 101 | |
| 102 // Re-read the key if necessary. | |
| 103 if (public_key_.empty() || reload_key) | |
| 104 ReadKeyFromFile(); | |
| 105 | |
| 106 if (!public_key_.empty()) { | |
| 107 crypto::SignatureVerifier verifier; | |
| 108 if (verifier.VerifyInit(kSignatureAlgorithm, sizeof(kSignatureAlgorithm), | |
| 109 reinterpret_cast<const uint8*>(&signature[0]), | |
| 110 signature.size(), | |
| 111 &public_key_[0], public_key_.size())) { | |
| 112 verifier.VerifyUpdate(reinterpret_cast<const uint8*>(data.c_str()), | |
| 113 data.length()); | |
| 114 status = verifier.VerifyFinal(); | |
| 115 } | |
| 116 } | |
| 117 | |
| 118 BrowserThread::PostTask(BrowserThread::UI, | |
| 119 FROM_HERE, | |
| 120 NewRunnableMethod(this, &PolicyKey::ReportResult, | |
| 121 callback, status)); | |
| 122 } | |
| 123 | |
| 124 void CrosUserPolicyCache::PolicyKey::ReportResult( | |
| 125 const StatusCallback& callback, | |
| 126 bool result) { | |
| 127 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 128 callback.Run(result); | |
| 129 } | |
| 130 | |
| 131 void CrosUserPolicyCache::PolicyKey::ReadKeyFromFile() { | |
| 132 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
| 133 | |
| 134 public_key_.clear(); | |
| 135 if (!file_util::PathExists(key_file_)) | |
| 136 return; | |
| 137 | |
| 138 int64 size = -1; | |
| 139 if (!file_util::GetFileSize(key_file_, &size)) { | |
| 140 LOG(ERROR) << "Failed to get file size for " << key_file_.value(); | |
| 141 return; | |
| 142 } | |
| 143 | |
| 144 const int64 kMaxSize = 1 * 1024 * 1024; // 1M should be sufficient. | |
| 145 if (size < 0 || size > kMaxSize) { | |
| 146 LOG(ERROR) << "Bogus policy key file size " << size; | |
| 147 return; | |
| 148 } | |
| 149 | |
| 150 std::vector<uint8> key_data(size); | |
| 151 if (!file_util::ReadFile(key_file_, | |
| 152 reinterpret_cast<char*>(&key_data[0]), | |
| 153 key_data.size())) { | |
| 154 LOG(ERROR) << "Failed to read " << key_file_.value(); | |
| 155 return; | |
| 156 } | |
| 157 | |
| 158 public_key_.swap(key_data); | |
| 159 } | |
| 160 | |
| 161 // Takes care of sending a new policy blob to session manager and reports back | |
| 162 // the status through a callback. | |
| 163 class CrosUserPolicyCache::StorePolicyOperation { | |
| 164 public: | |
| 165 typedef base::Callback<void(bool)> StatusCallback; | |
| 166 | |
| 167 // Creates and exectues an operation. | |
| 168 static StorePolicyOperation* Run(const em::PolicyFetchResponse& policy, | |
| 169 chromeos::LoginLibrary* login_library, | |
| 170 const StatusCallback& callback); | |
| 171 | |
| 172 // Cancels the operation, making sure that any pending callbacks get killed. | |
|
gfeher
2011/07/21 23:37:15
This doesn't really cancel the operation, just kil
Mattias Nissler (ping if slow)
2011/07/22 11:29:48
Done.
| |
| 173 void Cancel(); | |
| 174 | |
| 175 const em::PolicyFetchResponse& policy() { return policy_; } | |
| 176 | |
| 177 private: | |
| 178 StorePolicyOperation(const em::PolicyFetchResponse& policy, | |
| 179 const StatusCallback& callback); | |
| 180 | |
| 181 // StorePolicyOperation manages its own lifetime. | |
| 182 ~StorePolicyOperation() {} | |
| 183 | |
| 184 // A callback function suitable for passing to login_library. | |
| 185 static void StorePolicyCallback(void* delegate, bool result); | |
| 186 | |
| 187 em::PolicyFetchResponse policy_; | |
| 188 StatusCallback callback_; | |
| 189 | |
| 190 DISALLOW_COPY_AND_ASSIGN(StorePolicyOperation); | |
| 191 }; | |
| 192 | |
| 193 // static | |
| 194 CrosUserPolicyCache::StorePolicyOperation* | |
| 195 CrosUserPolicyCache::StorePolicyOperation::Run( | |
| 196 const em::PolicyFetchResponse& policy, | |
| 197 chromeos::LoginLibrary* login_library, | |
| 198 const StatusCallback& callback) { | |
| 199 StorePolicyOperation* op = new StorePolicyOperation(policy, callback); | |
| 200 std::string serialized; | |
| 201 if (!policy.SerializeToString(&serialized)) { | |
| 202 LOG(ERROR) << "Failed to serialize policy protobuf!"; | |
| 203 callback.Run(false); | |
| 204 delete op; | |
| 205 return NULL; | |
| 206 } | |
| 207 login_library->RequestStoreUserPolicy(serialized, StorePolicyCallback, op); | |
| 208 return op; | |
| 209 } | |
| 210 | |
| 211 void CrosUserPolicyCache::StorePolicyOperation::Cancel() { | |
| 212 callback_.Reset(); | |
| 213 } | |
| 214 | |
| 215 CrosUserPolicyCache::StorePolicyOperation::StorePolicyOperation( | |
| 216 const em::PolicyFetchResponse& policy, | |
| 217 const StatusCallback& callback) | |
| 218 : policy_(policy), | |
| 219 callback_(callback) {} | |
| 220 | |
| 221 // static | |
| 222 void CrosUserPolicyCache::StorePolicyOperation::StorePolicyCallback( | |
| 223 void* delegate, | |
| 224 bool result) { | |
| 225 StorePolicyOperation* op(static_cast<StorePolicyOperation*>(delegate)); | |
| 226 if (!op->callback_.is_null()) | |
| 227 op->callback_.Run(result); | |
| 228 delete op; | |
| 229 } | |
| 230 | |
| 231 class CrosUserPolicyCache::RetrievePolicyOperation { | |
| 232 public: | |
| 233 typedef base::Callback<void(bool, const em::PolicyFetchResponse&)> | |
| 234 ResultCallback; | |
| 235 | |
| 236 // Creates and executes an operation. | |
| 237 static RetrievePolicyOperation* Run(PolicyKey* key, | |
| 238 chromeos::LoginLibrary* login_library, | |
| 239 bool reload_key, | |
| 240 const ResultCallback& callback); | |
| 241 | |
| 242 // Cancels the operation, disengaging all pending callbacks. | |
|
gfeher
2011/07/21 23:37:15
Same here.
Mattias Nissler (ping if slow)
2011/07/22 11:29:48
Done.
| |
| 243 void Cancel(); | |
| 244 | |
| 245 private: | |
| 246 RetrievePolicyOperation(PolicyKey* key, | |
| 247 bool reload_key, | |
| 248 const ResultCallback& callback); | |
| 249 | |
| 250 // RetrievePolicyOperation manages its own lifetime. | |
| 251 ~RetrievePolicyOperation() {} | |
| 252 | |
| 253 // Decodes the policy data and triggers a signature check. | |
| 254 void OnPolicyRetrieved(const char* data, unsigned int size); | |
| 255 | |
| 256 // Handles the signature verification callback and reports the result. | |
| 257 void OnSignatureChecked(bool result); | |
| 258 | |
| 259 // Finishes the operation, makes the |callback_|, and deletes |this|. | |
| 260 void Finish(bool status); | |
| 261 | |
| 262 // A callback function suitable for passing to login_library. | |
| 263 static void RetrievePolicyCallback(void* delegate, | |
| 264 const char* data, | |
| 265 unsigned int size); | |
| 266 scoped_refptr<PolicyKey> key_; | |
| 267 bool reload_key_; | |
| 268 ResultCallback callback_; | |
| 269 em::PolicyFetchResponse policy_; | |
| 270 | |
| 271 DISALLOW_COPY_AND_ASSIGN(RetrievePolicyOperation); | |
| 272 }; | |
| 273 | |
| 274 // static | |
| 275 CrosUserPolicyCache::RetrievePolicyOperation* | |
| 276 CrosUserPolicyCache::RetrievePolicyOperation::Run( | |
| 277 PolicyKey* key, | |
| 278 chromeos::LoginLibrary* login_library, | |
| 279 bool reload_key, | |
| 280 const ResultCallback& callback) { | |
| 281 RetrievePolicyOperation* op = | |
| 282 new RetrievePolicyOperation(key, reload_key, callback); | |
| 283 login_library->RequestRetrieveUserPolicy(RetrievePolicyCallback, op); | |
| 284 return op; | |
| 285 } | |
| 286 | |
| 287 void CrosUserPolicyCache::RetrievePolicyOperation::Cancel() { | |
| 288 callback_.Reset(); | |
| 289 } | |
| 290 | |
| 291 CrosUserPolicyCache::RetrievePolicyOperation::RetrievePolicyOperation( | |
| 292 PolicyKey* key, | |
| 293 bool reload_key, | |
| 294 const ResultCallback& callback) | |
| 295 : key_(key), | |
| 296 reload_key_(reload_key), | |
| 297 callback_(callback) {} | |
| 298 | |
| 299 void CrosUserPolicyCache::RetrievePolicyOperation::OnPolicyRetrieved( | |
| 300 const char* data, | |
| 301 unsigned int size) { | |
| 302 if (!policy_.ParseFromArray(data, size) || | |
| 303 !policy_.has_policy_data() || | |
| 304 !policy_.has_policy_data_signature()) { | |
| 305 LOG(ERROR) << "Failed to decode policy"; | |
| 306 Finish(false); | |
| 307 return; | |
| 308 } | |
| 309 key_->CheckSignature(policy_.policy_data(), | |
| 310 policy_.policy_data_signature(), | |
| 311 reload_key_, | |
| 312 base::Bind(&RetrievePolicyOperation::OnSignatureChecked, | |
| 313 base::Unretained(this))); | |
| 314 } | |
| 315 | |
| 316 void CrosUserPolicyCache::RetrievePolicyOperation::OnSignatureChecked( | |
| 317 bool result) { | |
| 318 if (!result) | |
| 319 LOG(ERROR) << "User policy signature check failed."; | |
| 320 Finish(result); | |
| 321 } | |
| 322 | |
| 323 void CrosUserPolicyCache::RetrievePolicyOperation::Finish(bool status) { | |
| 324 if (!callback_.is_null()) | |
| 325 callback_.Run(status, policy_); | |
| 326 delete this; | |
| 327 } | |
| 328 | |
| 329 // static | |
| 330 void CrosUserPolicyCache::RetrievePolicyOperation::RetrievePolicyCallback( | |
| 331 void *delegate, | |
| 332 const char* data, | |
| 333 unsigned int size) { | |
| 334 static_cast<RetrievePolicyOperation*>(delegate)->OnPolicyRetrieved(data, | |
| 335 size); | |
| 336 } | |
| 337 | |
| 338 CrosUserPolicyCache::CrosUserPolicyCache( | |
| 339 chromeos::LoginLibrary* login_library, | |
| 340 CloudPolicyDataStore* data_store, | |
| 341 const FilePath& legacy_token_cache_file, | |
| 342 const FilePath& legacy_policy_cache_file) | |
| 343 : login_library_(login_library), | |
| 344 data_store_(data_store), | |
| 345 policy_cache_loaded_(false), | |
| 346 store_operation_(NULL), | |
| 347 retrieve_operation_(NULL), | |
| 348 legacy_cache_dir_(legacy_token_cache_file.DirName()), | |
| 349 ALLOW_THIS_IN_INITIALIZER_LIST( | |
| 350 legacy_token_cache_delegate_factory_(this)), | |
| 351 ALLOW_THIS_IN_INITIALIZER_LIST( | |
| 352 legacy_policy_cache_delegate_factory_(this)) { | |
| 353 DCHECK_EQ(legacy_token_cache_file.DirName().value(), | |
| 354 legacy_policy_cache_file.DirName().value()); | |
| 355 | |
| 356 FilePath key_file; | |
| 357 if (PathService::Get(chrome::DIR_USER_POLICY, &key_file)) | |
| 358 key_file.Append(kUserPolicyKeyFile); | |
| 359 else | |
| 360 NOTREACHED(); | |
| 361 key_ = new PolicyKey(key_file); | |
| 362 | |
| 363 legacy_token_loader_ = | |
| 364 new UserPolicyTokenLoader( | |
| 365 legacy_token_cache_delegate_factory_.GetWeakPtr(), | |
| 366 legacy_token_cache_file); | |
| 367 legacy_policy_cache_ = | |
| 368 new UserPolicyDiskCache( | |
| 369 legacy_policy_cache_delegate_factory_.GetWeakPtr(), | |
| 370 legacy_policy_cache_file); | |
| 371 } | |
| 372 | |
| 373 CrosUserPolicyCache::~CrosUserPolicyCache() { | |
| 374 CancelStore(); | |
| 375 CancelRetrieve(); | |
| 376 } | |
| 377 | |
| 378 void CrosUserPolicyCache::Load() { | |
| 379 key_->LoadKey(); | |
| 380 retrieve_operation_ = | |
| 381 RetrievePolicyOperation::Run( | |
| 382 key_, | |
| 383 login_library_, | |
| 384 false, | |
| 385 base::Bind(&CrosUserPolicyCache::OnPolicyLoadDone, | |
| 386 base::Unretained(this))); | |
| 387 } | |
| 388 | |
| 389 void CrosUserPolicyCache::SetPolicy(const em::PolicyFetchResponse& policy) { | |
| 390 CancelStore(); | |
| 391 set_last_policy_refresh_time(base::Time::NowFromSystemTime()); | |
| 392 store_operation_ = | |
| 393 StorePolicyOperation::Run(policy, | |
| 394 login_library_, | |
| 395 base::Bind(&CrosUserPolicyCache::OnPolicyStored, | |
| 396 base::Unretained(this))); | |
| 397 } | |
| 398 | |
| 399 void CrosUserPolicyCache::SetUnmanaged() { | |
| 400 base::Time now(base::Time::NowFromSystemTime()); | |
| 401 SetUnmanagedInternal(now); | |
| 402 | |
| 403 // Construct a policy blob with unmanaged state. | |
| 404 em::PolicyData policy_data; | |
| 405 policy_data.set_policy_type(data_store_->policy_type()); | |
| 406 policy_data.set_timestamp((now - base::Time::UnixEpoch()).InMilliseconds()); | |
|
gfeher
2011/07/21 23:37:15
I don't think it makes sense to stuff that into th
Mattias Nissler (ping if slow)
2011/07/22 11:29:48
Makes sense :) I'll keep it in mind when doing mor
| |
| 407 policy_data.set_state(em::PolicyData::UNMANAGED); | |
| 408 | |
| 409 em::PolicyFetchResponse policy; | |
| 410 if (!policy_data.SerializeToString(policy.mutable_policy_data())) { | |
| 411 LOG(ERROR) << "Failed to serialize policy_data"; | |
| 412 return; | |
| 413 } | |
| 414 | |
| 415 SetPolicy(policy); | |
| 416 } | |
| 417 | |
| 418 bool CrosUserPolicyCache::IsReady() { | |
| 419 return policy_cache_loaded_; | |
| 420 } | |
| 421 | |
| 422 bool CrosUserPolicyCache::DecodePolicyData(const em::PolicyData& policy_data, | |
| 423 PolicyMap* mandatory, | |
| 424 PolicyMap* recommended) { | |
| 425 em::CloudPolicySettings policy; | |
| 426 if (!policy.ParseFromString(policy_data.policy_value())) { | |
| 427 LOG(WARNING) << "Failed to parse CloudPolicySettings protobuf."; | |
| 428 return false; | |
| 429 } | |
| 430 DecodePolicy(policy, mandatory, recommended); | |
| 431 return true; | |
| 432 } | |
| 433 | |
| 434 void CrosUserPolicyCache::OnTokenLoaded(const std::string& token, | |
| 435 const std::string& device_id) { | |
| 436 data_store_->set_device_id(device_id); | |
| 437 data_store_->SetDeviceToken(token, true); | |
| 438 } | |
| 439 | |
| 440 void CrosUserPolicyCache::OnDiskCacheLoaded( | |
| 441 const em::CachedCloudPolicyResponse& policy) { | |
| 442 policy_cache_loaded_ = true; | |
| 443 if (policy.unmanaged()) { | |
| 444 SetUnmanagedInternal(base::Time::FromTimeT(policy.timestamp())); | |
| 445 } else if (policy.has_cloud_policy()) { | |
| 446 base::Time timestamp; | |
| 447 if (SetPolicyInternal(policy.cloud_policy(), ×tamp, true)) | |
| 448 set_last_policy_refresh_time(timestamp); | |
| 449 } | |
| 450 } | |
| 451 | |
| 452 void CrosUserPolicyCache::OnPolicyStored(bool result) { | |
| 453 DCHECK(store_operation_); | |
| 454 if (result) { | |
| 455 // Policy is stored successfully, reload from session_manager and apply. | |
| 456 // This helps us making sure we only use policy that session_manager has | |
| 457 // checked and confirmed to be good. | |
| 458 CancelRetrieve(); | |
| 459 retrieve_operation_ = | |
| 460 RetrievePolicyOperation::Run( | |
| 461 key_, | |
| 462 login_library_, | |
| 463 store_operation_->policy().has_new_public_key(), | |
| 464 base::Bind(&CrosUserPolicyCache::OnPolicyReloadDone, | |
| 465 base::Unretained(this))); | |
| 466 | |
| 467 // Now that we have installed the new policy blob, we can make sure that the | |
| 468 // old cache directory is removed. | |
| 469 if (!legacy_cache_dir_.empty()) { | |
| 470 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | |
| 471 NewRunnableFunction(&RemoveLegacyCacheDir, | |
| 472 legacy_cache_dir_)); | |
| 473 } | |
| 474 } else { | |
| 475 InformNotifier(CloudPolicySubsystem::LOCAL_ERROR, | |
| 476 CloudPolicySubsystem::POLICY_LOCAL_ERROR); | |
| 477 } | |
| 478 CancelStore(); | |
| 479 } | |
| 480 | |
| 481 void CrosUserPolicyCache::OnPolicyLoadDone( | |
| 482 bool result, | |
| 483 const em::PolicyFetchResponse& policy) { | |
| 484 DCHECK(retrieve_operation_); | |
| 485 CancelRetrieve(); | |
| 486 if (!result) { | |
| 487 // No policy present. Try to load the legacy token and policy cache. | |
| 488 legacy_token_loader_->Load(); | |
| 489 legacy_policy_cache_->Load(); | |
| 490 return; | |
| 491 } | |
| 492 | |
| 493 policy_cache_loaded_ = true; | |
| 494 | |
| 495 // We have new-style policy, no need to clean up. | |
| 496 legacy_cache_dir_.clear(); | |
| 497 | |
| 498 em::PolicyData policy_data; | |
| 499 if (!policy_data.ParseFromString(policy.policy_data())) { | |
| 500 LOG(WARNING) << "Failed to parse PolicyData protobuf."; | |
| 501 InformNotifier(CloudPolicySubsystem::LOCAL_ERROR, | |
| 502 CloudPolicySubsystem::POLICY_LOCAL_ERROR); | |
| 503 data_store_->SetDeviceToken(std::string(), true); | |
| 504 return; | |
| 505 } | |
| 506 if (policy_data.request_token().empty() || | |
| 507 policy_data.username().empty() || | |
| 508 policy_data.device_id().empty()) { | |
| 509 LOG(WARNING) << "Policy protobuf is missing credentials"; | |
| 510 InformNotifier(CloudPolicySubsystem::LOCAL_ERROR, | |
| 511 CloudPolicySubsystem::POLICY_LOCAL_ERROR); | |
| 512 data_store_->SetDeviceToken(std::string(), true); | |
| 513 return; | |
| 514 } | |
| 515 data_store_->set_device_id(policy_data.device_id()); | |
| 516 data_store_->SetDeviceToken(policy_data.request_token(), true); | |
| 517 if (SetPolicyInternal(policy, NULL, true)) | |
| 518 set_last_policy_refresh_time(base::Time::NowFromSystemTime()); | |
| 519 } | |
| 520 | |
| 521 void CrosUserPolicyCache::OnPolicyReloadDone( | |
| 522 bool result, | |
| 523 const em::PolicyFetchResponse& policy) { | |
| 524 DCHECK(retrieve_operation_); | |
| 525 policy_cache_loaded_ = true; | |
| 526 CancelRetrieve(); | |
| 527 if (result) { | |
| 528 if (SetPolicyInternal(policy, NULL, false)) | |
| 529 set_last_policy_refresh_time(base::Time::NowFromSystemTime()); | |
| 530 } else { | |
| 531 InformNotifier(CloudPolicySubsystem::LOCAL_ERROR, | |
| 532 CloudPolicySubsystem::POLICY_LOCAL_ERROR); | |
| 533 } | |
| 534 } | |
| 535 | |
| 536 void CrosUserPolicyCache::CancelStore() { | |
| 537 if (store_operation_) { | |
| 538 store_operation_->Cancel(); | |
| 539 store_operation_ = NULL; | |
| 540 } | |
| 541 } | |
| 542 | |
| 543 void CrosUserPolicyCache::CancelRetrieve() { | |
| 544 if (retrieve_operation_) { | |
| 545 retrieve_operation_->Cancel(); | |
| 546 retrieve_operation_ = NULL; | |
| 547 } | |
| 548 } | |
| 549 | |
| 550 // static | |
| 551 void CrosUserPolicyCache::RemoveLegacyCacheDir(const FilePath& dir) { | |
| 552 if (!file_util::Delete(dir, true)) | |
| 553 PLOG(ERROR) << "Failed to remove " << dir.value(); | |
| 554 } | |
| 555 | |
| 556 } // namespace policy | |
| OLD | NEW |