Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/policy/cloud_policy_cache.h" | 5 #include "chrome/browser/policy/cloud_policy_cache.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 | 8 |
| 9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/task.h" | 11 #include "base/task.h" |
| 12 #include "base/values.h" | 12 #include "base/values.h" |
| 13 #include "chrome/browser/browser_thread.h" | 13 #include "chrome/browser/browser_thread.h" |
| 14 #include "chrome/browser/policy/configuration_policy_pref_store.h" | |
| 14 #include "chrome/browser/policy/proto/cloud_policy.pb.h" | 15 #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_constants.h" | 16 #include "chrome/browser/policy/proto/device_management_constants.h" |
| 17 #include "chrome/browser/policy/proto/device_management_local.pb.h" | 17 #include "chrome/browser/policy/proto/device_management_local.pb.h" |
| 18 | 18 |
| 19 using google::protobuf::RepeatedField; | 19 using google::protobuf::RepeatedField; |
| 20 using google::protobuf::RepeatedPtrField; | 20 using google::protobuf::RepeatedPtrField; |
| 21 | 21 |
| 22 // This CloudPolicyCache currently supports two protocols for the interaction | 22 // This CloudPolicyCache currently supports two protocols for the interaction |
| 23 // with DMServer: the old "DevicePolicy" format, which is being used in the | 23 // with DMServer: the old "DevicePolicy" format, which is being used in the |
| 24 // CrOS Pilot Program and will be deprecated afterwards, and the new | 24 // CrOS Pilot Program and will be deprecated afterwards, and the new |
| 25 // "CloudPolicy" format, which will be used exclusively after the public launch | 25 // "CloudPolicy" format, which will be used exclusively after the public launch |
| 26 // of ChromeOS. | 26 // of ChromeOS. |
| 27 | 27 |
| 28 namespace policy { | 28 namespace policy { |
| 29 | 29 |
| 30 // A thin ConfigurationPolicyProvider implementation sitting on top of | |
| 31 // CloudPolicyCache for hooking up with ConfigurationPolicyPrefStore. | |
| 32 class CloudPolicyCache::CloudPolicyProvider | |
| 33 : public ConfigurationPolicyProvider { | |
| 34 public: | |
| 35 CloudPolicyProvider(const PolicyDefinitionList* policy_list, | |
| 36 CloudPolicyCache* cache, | |
| 37 CloudPolicyCache::PolicyLevel level) | |
| 38 : ConfigurationPolicyProvider(policy_list), | |
| 39 cache_(cache), | |
| 40 level_(level) {} | |
| 41 virtual ~CloudPolicyProvider() {} | |
| 42 | |
| 43 virtual bool Provide(ConfigurationPolicyStoreInterface* store) { | |
| 44 if (cache_->has_device_policy()) { | |
|
gfeher
2011/02/14 17:28:50
Shouldn't this be has_cloud_policy() ?
Jakob Kummerow
2011/02/21 12:12:15
Done. Good catch!
| |
| 45 if (level_ == POLICY_LEVEL_MANDATORY) | |
| 46 ApplyPolicyMap(&cache_->mandatory_policy_, store); | |
| 47 else if (level_ == POLICY_LEVEL_RECOMMENDED) | |
| 48 ApplyPolicyMap(&cache_->recommended_policy_, store); | |
| 49 } else { | |
| 50 ApplyPolicyValueTree(cache_->device_policy_.get(), store); | |
| 51 } | |
| 52 return true; | |
| 53 } | |
| 54 | |
| 55 virtual bool IsInitializationComplete() const { | |
| 56 return cache_->initialization_complete_; | |
| 57 } | |
| 58 | |
| 59 virtual void AddObserver(ConfigurationPolicyProvider::Observer* observer) { | |
| 60 cache_->observer_list_.AddObserver(observer); | |
| 61 } | |
| 62 virtual void RemoveObserver(ConfigurationPolicyProvider::Observer* observer) { | |
| 63 cache_->observer_list_.RemoveObserver(observer); | |
| 64 } | |
| 65 | |
| 66 private: | |
| 67 // The underlying policy cache. | |
| 68 CloudPolicyCache* cache_; | |
| 69 // Policy level this provider will handle. | |
| 70 CloudPolicyCache::PolicyLevel level_; | |
| 71 | |
| 72 DISALLOW_COPY_AND_ASSIGN(CloudPolicyProvider); | |
| 73 }; | |
| 74 | |
| 30 // Saves policy information to a file. | 75 // Saves policy information to a file. |
| 31 class PersistPolicyTask : public Task { | 76 class PersistPolicyTask : public Task { |
| 32 public: | 77 public: |
| 33 PersistPolicyTask(const FilePath& path, | 78 PersistPolicyTask(const FilePath& path, |
| 34 const em::CloudPolicyResponse* cloud_policy_response, | 79 const em::CloudPolicyResponse* cloud_policy_response, |
| 35 const em::DevicePolicyResponse* device_policy_response, | 80 const em::DevicePolicyResponse* device_policy_response, |
| 36 const bool is_unmanaged) | 81 const bool is_unmanaged) |
| 37 : path_(path), | 82 : path_(path), |
| 38 cloud_policy_response_(cloud_policy_response), | 83 cloud_policy_response_(cloud_policy_response), |
| 39 device_policy_response_(device_policy_response), | 84 device_policy_response_(device_policy_response), |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 72 if (file_util::WriteFile(path_, data.c_str(), size) != size) { | 117 if (file_util::WriteFile(path_, data.c_str(), size) != size) { |
| 73 LOG(WARNING) << "Failed to write " << path_.value(); | 118 LOG(WARNING) << "Failed to write " << path_.value(); |
| 74 return; | 119 return; |
| 75 } | 120 } |
| 76 } | 121 } |
| 77 | 122 |
| 78 CloudPolicyCache::CloudPolicyCache( | 123 CloudPolicyCache::CloudPolicyCache( |
| 79 const FilePath& backing_file_path) | 124 const FilePath& backing_file_path) |
| 80 : backing_file_path_(backing_file_path), | 125 : backing_file_path_(backing_file_path), |
| 81 device_policy_(new DictionaryValue), | 126 device_policy_(new DictionaryValue), |
| 82 fresh_policy_(false), | 127 initialization_complete_(false), |
| 83 is_unmanaged_(false), | 128 is_unmanaged_(false), |
| 84 has_device_policy_(false) { | 129 has_device_policy_(false) { |
| 130 managed_policy_provider_.reset( | |
| 131 new CloudPolicyProvider( | |
| 132 ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList(), | |
| 133 this, | |
| 134 POLICY_LEVEL_MANDATORY)); | |
| 135 recommended_policy_provider_.reset( | |
| 136 new CloudPolicyProvider( | |
| 137 ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList(), | |
| 138 this, | |
| 139 POLICY_LEVEL_RECOMMENDED)); | |
| 85 } | 140 } |
| 86 | 141 |
| 87 CloudPolicyCache::~CloudPolicyCache() {} | 142 CloudPolicyCache::~CloudPolicyCache() { |
| 143 FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer, | |
| 144 observer_list_, OnProviderGoingAway()); | |
| 145 } | |
| 88 | 146 |
| 89 void CloudPolicyCache::LoadPolicyFromFile() { | 147 void CloudPolicyCache::LoadFromFile() { |
| 90 // TODO(jkummerow): This method is doing file IO during browser startup. In | 148 // TODO(jkummerow): This method is doing file IO during browser startup. In |
| 91 // the long run it would be better to delay this until the FILE thread exists. | 149 // the long run it would be better to delay this until the FILE thread exists. |
| 92 if (!file_util::PathExists(backing_file_path_) || fresh_policy_) { | 150 if (!file_util::PathExists(backing_file_path_) || initialization_complete_) { |
| 93 return; | 151 return; |
| 94 } | 152 } |
| 95 | 153 |
| 96 // Read the protobuf from the file. | 154 // Read the protobuf from the file. |
| 97 std::string data; | 155 std::string data; |
| 98 if (!file_util::ReadFileToString(backing_file_path_, &data)) { | 156 if (!file_util::ReadFileToString(backing_file_path_, &data)) { |
| 99 LOG(WARNING) << "Failed to read policy data from " | 157 LOG(WARNING) << "Failed to read policy data from " |
| 100 << backing_file_path_.value(); | 158 << backing_file_path_.value(); |
| 101 return; | 159 return; |
| 102 } | 160 } |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 123 LOG(WARNING) << "Decoding policy data failed."; | 181 LOG(WARNING) << "Decoding policy data failed."; |
| 124 return; | 182 return; |
| 125 } | 183 } |
| 126 } | 184 } |
| 127 if (timestamp > base::Time::NowFromSystemTime()) { | 185 if (timestamp > base::Time::NowFromSystemTime()) { |
| 128 LOG(WARNING) << "Rejected policy data from " << backing_file_path_.value() | 186 LOG(WARNING) << "Rejected policy data from " << backing_file_path_.value() |
| 129 << ", file is from the future."; | 187 << ", file is from the future."; |
| 130 return; | 188 return; |
| 131 } | 189 } |
| 132 // Swap in the new policy information. | 190 // Swap in the new policy information. |
| 133 if (is_unmanaged_) { | 191 if (cached_response.has_cloud_policy()) { |
| 134 base::AutoLock lock(lock_); | 192 mandatory_policy_.swap(mandatory_policy); |
| 135 last_policy_refresh_time_ = timestamp; | 193 recommended_policy_.swap(recommended_policy); |
| 136 return; | 194 has_device_policy_ = false; |
| 137 } else if (cached_response.has_cloud_policy()) { | |
| 138 if (!fresh_policy_) { | |
| 139 base::AutoLock lock(lock_); | |
| 140 mandatory_policy_.swap(mandatory_policy); | |
| 141 recommended_policy_.swap(recommended_policy); | |
| 142 last_policy_refresh_time_ = timestamp; | |
| 143 has_device_policy_ = false; | |
| 144 } | |
| 145 } else if (cached_response.has_device_policy()) { | 195 } else if (cached_response.has_device_policy()) { |
| 146 scoped_ptr<DictionaryValue> value( | 196 scoped_ptr<DictionaryValue> value( |
| 147 DecodeDevicePolicy(cached_response.device_policy())); | 197 DecodeDevicePolicy(cached_response.device_policy())); |
| 148 if (!fresh_policy_) { | 198 device_policy_.reset(value.release()); |
| 149 base::AutoLock lock(lock_); | 199 has_device_policy_ = true; |
| 150 device_policy_.reset(value.release()); | |
| 151 last_policy_refresh_time_ = timestamp; | |
| 152 has_device_policy_ = true; | |
| 153 } | |
| 154 } | 200 } |
| 201 last_policy_refresh_time_ = timestamp; | |
| 202 initialization_complete_ = true; | |
| 203 | |
| 204 FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer, | |
| 205 observer_list_, OnUpdatePolicy()); | |
| 155 } | 206 } |
| 156 | 207 |
| 157 bool CloudPolicyCache::SetPolicy(const em::CloudPolicyResponse& policy) { | 208 bool CloudPolicyCache::SetPolicy(const em::CloudPolicyResponse& policy) { |
| 158 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 209 DCHECK(CalledOnValidThread()); |
| 159 is_unmanaged_ = false; | 210 is_unmanaged_ = false; |
| 160 base::Time timestamp; | 211 base::Time timestamp; |
| 161 PolicyMapType mandatory_policy; | 212 PolicyMapType mandatory_policy; |
| 162 PolicyMapType recommended_policy; | 213 PolicyMapType recommended_policy; |
| 163 bool ok = DecodePolicyResponse(policy, &mandatory_policy, &recommended_policy, | 214 bool ok = DecodePolicyResponse(policy, &mandatory_policy, &recommended_policy, |
| 164 ×tamp); | 215 ×tamp); |
| 165 if (!ok) { | 216 if (!ok) { |
| 166 // TODO(jkummerow): Signal error to PolicyProvider. | 217 // TODO(jkummerow): Signal error to CloudPolicyController. |
| 167 return false; | 218 return false; |
| 168 } | 219 } |
| 169 const bool new_policy_differs = | 220 const bool new_policy_differs = |
| 170 !Equals(mandatory_policy, mandatory_policy_) || | 221 !Equals(mandatory_policy, mandatory_policy_) || |
| 171 !Equals(recommended_policy, recommended_policy_); | 222 !Equals(recommended_policy, recommended_policy_); |
| 172 { | 223 mandatory_policy_.swap(mandatory_policy); |
| 173 base::AutoLock lock(lock_); | 224 recommended_policy_.swap(recommended_policy); |
| 174 mandatory_policy_.swap(mandatory_policy); | 225 initialization_complete_ = true; |
| 175 recommended_policy_.swap(recommended_policy); | 226 last_policy_refresh_time_ = timestamp; |
| 176 fresh_policy_ = true; | 227 has_device_policy_ = false; |
| 177 last_policy_refresh_time_ = timestamp; | 228 |
| 178 has_device_policy_ = false; | 229 FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer, |
| 179 } | 230 observer_list_, OnUpdatePolicy()); |
| 180 | 231 |
| 181 em::CloudPolicyResponse* policy_copy = new em::CloudPolicyResponse; | 232 em::CloudPolicyResponse* policy_copy = new em::CloudPolicyResponse; |
| 182 policy_copy->CopyFrom(policy); | 233 policy_copy->CopyFrom(policy); |
| 183 BrowserThread::PostTask( | 234 BrowserThread::PostTask( |
| 184 BrowserThread::FILE, | 235 BrowserThread::FILE, |
| 185 FROM_HERE, | 236 FROM_HERE, |
| 186 new PersistPolicyTask(backing_file_path_, policy_copy, NULL, false)); | 237 new PersistPolicyTask(backing_file_path_, policy_copy, NULL, false)); |
| 187 return new_policy_differs; | 238 return new_policy_differs; |
| 188 } | 239 } |
| 189 | 240 |
| 190 bool CloudPolicyCache::SetDevicePolicy(const em::DevicePolicyResponse& policy) { | 241 bool CloudPolicyCache::SetDevicePolicy(const em::DevicePolicyResponse& policy) { |
| 191 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 242 DCHECK(CalledOnValidThread()); |
| 192 is_unmanaged_ = false; | 243 is_unmanaged_ = false; |
| 193 DictionaryValue* value = DecodeDevicePolicy(policy); | 244 DictionaryValue* value = DecodeDevicePolicy(policy); |
| 194 const bool new_policy_differs = !(value->Equals(device_policy_.get())); | 245 const bool new_policy_differs = !(value->Equals(device_policy_.get())); |
| 195 base::Time now(base::Time::NowFromSystemTime()); | 246 base::Time now(base::Time::NowFromSystemTime()); |
| 196 { | 247 device_policy_.reset(value); |
| 197 base::AutoLock lock(lock_); | 248 initialization_complete_ = true; |
| 198 device_policy_.reset(value); | 249 last_policy_refresh_time_ = now; |
| 199 fresh_policy_ = true; | 250 has_device_policy_ = true; |
| 200 last_policy_refresh_time_ = now; | 251 |
| 201 has_device_policy_ = true; | 252 FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer, |
| 202 } | 253 observer_list_, OnUpdatePolicy()); |
| 203 | 254 |
| 204 em::DevicePolicyResponse* policy_copy = new em::DevicePolicyResponse; | 255 em::DevicePolicyResponse* policy_copy = new em::DevicePolicyResponse; |
| 205 policy_copy->CopyFrom(policy); | 256 policy_copy->CopyFrom(policy); |
| 206 BrowserThread::PostTask( | 257 BrowserThread::PostTask( |
| 207 BrowserThread::FILE, | 258 BrowserThread::FILE, |
| 208 FROM_HERE, | 259 FROM_HERE, |
| 209 new PersistPolicyTask(backing_file_path_, NULL, policy_copy, false)); | 260 new PersistPolicyTask(backing_file_path_, NULL, policy_copy, false)); |
| 210 return new_policy_differs; | 261 return new_policy_differs; |
| 211 } | 262 } |
| 212 | 263 |
| 213 DictionaryValue* CloudPolicyCache::GetDevicePolicy() { | 264 ConfigurationPolicyProvider* CloudPolicyCache::GetManagedPolicyProvider() { |
| 214 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 265 DCHECK(CalledOnValidThread()); |
| 215 base::AutoLock lock(lock_); | 266 return managed_policy_provider_.get(); |
| 216 return device_policy_->DeepCopy(); | |
| 217 } | 267 } |
| 218 | 268 |
| 219 const CloudPolicyCache::PolicyMapType* | 269 ConfigurationPolicyProvider* CloudPolicyCache::GetRecommendedPolicyProvider() { |
| 220 CloudPolicyCache::GetMandatoryPolicy() const { | 270 DCHECK(CalledOnValidThread()); |
| 221 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 271 return recommended_policy_provider_.get(); |
| 222 return &mandatory_policy_; | |
| 223 } | |
| 224 | |
| 225 const CloudPolicyCache::PolicyMapType* | |
| 226 CloudPolicyCache::GetRecommendedPolicy() const { | |
| 227 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 228 return &recommended_policy_; | |
| 229 } | 272 } |
| 230 | 273 |
| 231 void CloudPolicyCache::SetUnmanaged() { | 274 void CloudPolicyCache::SetUnmanaged() { |
| 232 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 275 DCHECK(CalledOnValidThread()); |
| 233 is_unmanaged_ = true; | 276 is_unmanaged_ = true; |
| 234 { | 277 mandatory_policy_.clear(); |
| 235 base::AutoLock lock(lock_); | 278 recommended_policy_.clear(); |
| 236 mandatory_policy_.clear(); | 279 device_policy_.reset(new DictionaryValue); |
| 237 recommended_policy_.clear(); | 280 last_policy_refresh_time_ = base::Time::NowFromSystemTime(); |
| 238 device_policy_.reset(new DictionaryValue); | 281 |
| 239 last_policy_refresh_time_ = base::Time::NowFromSystemTime(); | 282 FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer, |
| 240 } | 283 observer_list_, OnUpdatePolicy()); |
| 284 | |
| 241 BrowserThread::PostTask( | 285 BrowserThread::PostTask( |
| 242 BrowserThread::FILE, | 286 BrowserThread::FILE, |
| 243 FROM_HERE, | 287 FROM_HERE, |
| 244 new PersistPolicyTask(backing_file_path_, NULL, NULL, true)); | 288 new PersistPolicyTask(backing_file_path_, NULL, NULL, true)); |
| 245 } | 289 } |
| 246 | 290 |
| 247 // static | 291 // static |
| 248 bool CloudPolicyCache::DecodePolicyResponse( | 292 bool CloudPolicyCache::DecodePolicyResponse( |
| 249 const em::CloudPolicyResponse& policy_response, | 293 const em::CloudPolicyResponse& policy_response, |
| 250 PolicyMapType* mandatory, | 294 PolicyMapType* mandatory, |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 411 CloudPolicyCache::DecodeValue(named_value->value()); | 455 CloudPolicyCache::DecodeValue(named_value->value()); |
| 412 if (decoded_value) | 456 if (decoded_value) |
| 413 result->Set(named_value->name(), decoded_value); | 457 result->Set(named_value->name(), decoded_value); |
| 414 } | 458 } |
| 415 } | 459 } |
| 416 } | 460 } |
| 417 return result; | 461 return result; |
| 418 } | 462 } |
| 419 | 463 |
| 420 } // namespace policy | 464 } // namespace policy |
| OLD | NEW |