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 |