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/device_management_policy_provider.h" | |
6 | |
7 #include <algorithm> | |
8 | |
9 #include "base/command_line.h" | |
10 #include "base/file_util.h" | |
11 #include "base/path_service.h" | |
12 #include "base/rand_util.h" | |
13 #include "base/task.h" | |
14 #include "chrome/browser/browser_thread.h" | |
15 #include "chrome/browser/policy/cloud_policy_cache.h" | |
16 #include "chrome/browser/policy/device_management_backend.h" | |
17 #include "chrome/browser/policy/profile_policy_context.h" | |
18 #include "chrome/browser/policy/proto/device_management_constants.h" | |
19 #include "chrome/browser/profiles/profile.h" | |
20 #include "chrome/common/chrome_paths.h" | |
21 #include "chrome/common/chrome_switches.h" | |
22 #include "chrome/common/notification_service.h" | |
23 #include "chrome/common/notification_type.h" | |
24 | |
25 namespace policy { | |
26 | |
27 namespace em = enterprise_management; | |
28 | |
29 // The maximum ratio in percent of the policy refresh rate we use for adjusting | |
30 // the policy refresh time instant. The rationale is to avoid load spikes from | |
31 // many devices that were set up in sync for some reason. | |
32 const int kPolicyRefreshDeviationFactorPercent = 10; | |
33 // Maximum deviation we are willing to accept. | |
34 const int64 kPolicyRefreshDeviationMaxInMilliseconds = 30 * 60 * 1000; | |
35 | |
36 // These are the base values for delays before retrying after an error. They | |
37 // will be doubled each time they are used. | |
38 const int64 kPolicyRefreshErrorDelayInMilliseconds = 3 * 1000; // 3 seconds | |
39 const int64 kDeviceTokenRefreshErrorDelayInMilliseconds = 3 * 1000; | |
40 // For unmanaged devices, check once per day whether they're still unmanaged. | |
41 const int64 kPolicyRefreshUnmanagedDeviceInMilliseconds = 24 * 60 * 60 * 1000; | |
42 | |
43 const FilePath::StringType kDeviceTokenFilename = FILE_PATH_LITERAL("Token"); | |
44 const FilePath::StringType kPolicyFilename = FILE_PATH_LITERAL("Policy"); | |
45 | |
46 // Calls back into the provider to refresh policy. | |
47 class DeviceManagementPolicyProvider::RefreshTask : public CancelableTask { | |
48 public: | |
49 explicit RefreshTask(DeviceManagementPolicyProvider* provider) | |
50 : provider_(provider) {} | |
51 | |
52 // Task implementation: | |
53 virtual void Run() { | |
54 if (provider_) | |
55 provider_->RefreshTaskExecute(); | |
56 } | |
57 | |
58 // CancelableTask implementation: | |
59 virtual void Cancel() { | |
60 provider_ = NULL; | |
61 } | |
62 | |
63 private: | |
64 DeviceManagementPolicyProvider* provider_; | |
65 }; | |
66 | |
67 DeviceManagementPolicyProvider::DeviceManagementPolicyProvider( | |
68 const ConfigurationPolicyProvider::PolicyDefinitionList* policy_list, | |
69 DeviceManagementBackend* backend, | |
70 Profile* profile) | |
71 : ConfigurationPolicyProvider(policy_list) { | |
72 Initialize(backend, | |
73 profile, | |
74 ProfilePolicyContext::kDefaultPolicyRefreshRateInMilliseconds, | |
75 kPolicyRefreshDeviationFactorPercent, | |
76 kPolicyRefreshDeviationMaxInMilliseconds, | |
77 kPolicyRefreshErrorDelayInMilliseconds, | |
78 kDeviceTokenRefreshErrorDelayInMilliseconds, | |
79 kPolicyRefreshUnmanagedDeviceInMilliseconds); | |
80 } | |
81 | |
82 DeviceManagementPolicyProvider::~DeviceManagementPolicyProvider() { | |
83 FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer, | |
84 observer_list_, | |
85 OnProviderGoingAway()); | |
86 CancelRefreshTask(); | |
87 } | |
88 | |
89 bool DeviceManagementPolicyProvider::Provide( | |
90 ConfigurationPolicyStoreInterface* policy_store) { | |
91 if (cache_->has_device_policy()) { | |
92 scoped_ptr<DictionaryValue> policies(cache_->GetDevicePolicy()); | |
93 ApplyPolicyValueTree(policies.get(), policy_store); | |
94 } else { | |
95 ApplyPolicyMap(cache_->GetMandatoryPolicy(), policy_store); | |
96 // TODO(jkummerow, mnissler): provide recommended policy. | |
97 } | |
98 return true; | |
99 } | |
100 | |
101 bool DeviceManagementPolicyProvider::IsInitializationComplete() const { | |
102 return !cache_->last_policy_refresh_time().is_null(); | |
103 } | |
104 | |
105 void DeviceManagementPolicyProvider::HandlePolicyResponse( | |
106 const em::DevicePolicyResponse& response) { | |
107 DCHECK(TokenAvailable()); | |
108 if (cache_->SetDevicePolicy(response)) { | |
109 initial_fetch_done_ = true; | |
110 NotifyCloudPolicyUpdate(); | |
111 } | |
112 SetState(STATE_POLICY_VALID); | |
113 } | |
114 | |
115 void DeviceManagementPolicyProvider::HandleCloudPolicyResponse( | |
116 const em::CloudPolicyResponse& response) { | |
117 DCHECK(TokenAvailable()); | |
118 if (cache_->SetPolicy(response)) { | |
119 initial_fetch_done_ = true; | |
120 NotifyCloudPolicyUpdate(); | |
121 } | |
122 SetState(STATE_POLICY_VALID); | |
123 } | |
124 | |
125 void DeviceManagementPolicyProvider::OnError( | |
126 DeviceManagementBackend::ErrorCode code) { | |
127 DCHECK(TokenAvailable()); | |
128 if (code == DeviceManagementBackend::kErrorServiceDeviceNotFound || | |
129 code == DeviceManagementBackend::kErrorServiceManagementTokenInvalid) { | |
130 LOG(WARNING) << "The device token was either invalid or unknown to the " | |
131 << "device manager, re-registering device."; | |
132 SetState(STATE_TOKEN_RESET); | |
133 } else if (code == | |
134 DeviceManagementBackend::kErrorServiceManagementNotSupported) { | |
135 VLOG(1) << "The device is no longer managed, resetting device token."; | |
136 SetState(STATE_TOKEN_RESET); | |
137 } else if (!fallback_to_old_protocol_ && | |
138 code == DeviceManagementBackend::kErrorRequestInvalid) { | |
139 LOG(WARNING) << "Device management server doesn't understand new protocol," | |
140 << " falling back to old request."; | |
141 fallback_to_old_protocol_ = true; | |
142 SetState(STATE_TOKEN_VALID); // Triggers SendPolicyRequest() immediately. | |
143 } else { | |
144 LOG(WARNING) << "Could not provide policy from the device manager (error = " | |
145 << code << "), will retry in " | |
146 << (effective_policy_refresh_error_delay_ms_ / 1000) | |
147 << " seconds."; | |
148 SetState(STATE_POLICY_ERROR); | |
149 } | |
150 } | |
151 | |
152 void DeviceManagementPolicyProvider::OnTokenSuccess() { | |
153 DCHECK(!TokenAvailable()); | |
154 SetState(STATE_TOKEN_VALID); | |
155 } | |
156 | |
157 void DeviceManagementPolicyProvider::OnTokenError() { | |
158 DCHECK(!TokenAvailable()); | |
159 LOG(WARNING) << "Could not retrieve device token."; | |
160 SetState(STATE_TOKEN_ERROR); | |
161 } | |
162 | |
163 void DeviceManagementPolicyProvider::OnNotManaged() { | |
164 DCHECK(!TokenAvailable()); | |
165 VLOG(1) << "This device is not managed."; | |
166 cache_->SetUnmanaged(); | |
167 SetState(STATE_UNMANAGED); | |
168 } | |
169 | |
170 void DeviceManagementPolicyProvider::SetRefreshRate( | |
171 int64 refresh_rate_milliseconds) { | |
172 policy_refresh_rate_ms_ = refresh_rate_milliseconds; | |
173 | |
174 // Reschedule the refresh task if necessary. | |
175 if (state_ == STATE_POLICY_VALID) | |
176 SetState(STATE_POLICY_VALID); | |
177 } | |
178 | |
179 DeviceManagementPolicyProvider::DeviceManagementPolicyProvider( | |
180 const PolicyDefinitionList* policy_list, | |
181 DeviceManagementBackend* backend, | |
182 Profile* profile, | |
183 int64 policy_refresh_rate_ms, | |
184 int policy_refresh_deviation_factor_percent, | |
185 int64 policy_refresh_deviation_max_ms, | |
186 int64 policy_refresh_error_delay_ms, | |
187 int64 token_fetch_error_delay_ms, | |
188 int64 unmanaged_device_refresh_rate_ms) | |
189 : ConfigurationPolicyProvider(policy_list) { | |
190 Initialize(backend, | |
191 profile, | |
192 policy_refresh_rate_ms, | |
193 policy_refresh_deviation_factor_percent, | |
194 policy_refresh_deviation_max_ms, | |
195 policy_refresh_error_delay_ms, | |
196 token_fetch_error_delay_ms, | |
197 unmanaged_device_refresh_rate_ms); | |
198 } | |
199 | |
200 void DeviceManagementPolicyProvider::Initialize( | |
201 DeviceManagementBackend* backend, | |
202 Profile* profile, | |
203 int64 policy_refresh_rate_ms, | |
204 int policy_refresh_deviation_factor_percent, | |
205 int64 policy_refresh_deviation_max_ms, | |
206 int64 policy_refresh_error_delay_ms, | |
207 int64 token_fetch_error_delay_ms, | |
208 int64 unmanaged_device_refresh_rate_ms) { | |
209 DCHECK(profile); | |
210 backend_.reset(backend); | |
211 profile_ = profile; | |
212 fallback_to_old_protocol_ = false; | |
213 storage_dir_ = GetOrCreateDeviceManagementDir(profile_->GetPath()); | |
214 state_ = STATE_INITIALIZING; | |
215 initial_fetch_done_ = false; | |
216 refresh_task_ = NULL; | |
217 policy_refresh_rate_ms_ = policy_refresh_rate_ms; | |
218 policy_refresh_deviation_factor_percent_ = | |
219 policy_refresh_deviation_factor_percent; | |
220 policy_refresh_deviation_max_ms_ = policy_refresh_deviation_max_ms; | |
221 policy_refresh_error_delay_ms_ = policy_refresh_error_delay_ms; | |
222 effective_policy_refresh_error_delay_ms_ = policy_refresh_error_delay_ms; | |
223 token_fetch_error_delay_ms_ = token_fetch_error_delay_ms; | |
224 effective_token_fetch_error_delay_ms_ = token_fetch_error_delay_ms; | |
225 unmanaged_device_refresh_rate_ms_ = unmanaged_device_refresh_rate_ms; | |
226 | |
227 const FilePath policy_path = storage_dir_.Append(kPolicyFilename); | |
228 cache_.reset(new CloudPolicyCache(policy_path)); | |
229 cache_->LoadPolicyFromFile(); | |
230 | |
231 SetDeviceTokenFetcher(new DeviceTokenFetcher(backend_.get(), profile, | |
232 GetTokenPath())); | |
233 | |
234 if (cache_->is_unmanaged()) { | |
235 // This is a non-first login on an unmanaged device. | |
236 SetState(STATE_UNMANAGED); | |
237 } else { | |
238 SetState(STATE_INITIALIZING); | |
239 } | |
240 } | |
241 | |
242 void DeviceManagementPolicyProvider::AddObserver( | |
243 ConfigurationPolicyProvider::Observer* observer) { | |
244 observer_list_.AddObserver(observer); | |
245 } | |
246 | |
247 void DeviceManagementPolicyProvider::RemoveObserver( | |
248 ConfigurationPolicyProvider::Observer* observer) { | |
249 observer_list_.RemoveObserver(observer); | |
250 } | |
251 | |
252 void DeviceManagementPolicyProvider::SendPolicyRequest() { | |
253 if (!fallback_to_old_protocol_) { | |
254 em::CloudPolicyRequest policy_request; | |
255 policy_request.set_policy_scope(kChromePolicyScope); | |
256 backend_->ProcessCloudPolicyRequest(token_fetcher_->GetDeviceToken(), | |
257 token_fetcher_->GetDeviceID(), | |
258 policy_request, this); | |
259 } else { | |
260 em::DevicePolicyRequest policy_request; | |
261 policy_request.set_policy_scope(kChromePolicyScope); | |
262 em::DevicePolicySettingRequest* setting = | |
263 policy_request.add_setting_request(); | |
264 setting->set_key(kChromeDevicePolicySettingKey); | |
265 setting->set_watermark(""); | |
266 backend_->ProcessPolicyRequest(token_fetcher_->GetDeviceToken(), | |
267 token_fetcher_->GetDeviceID(), | |
268 policy_request, this); | |
269 } | |
270 } | |
271 | |
272 void DeviceManagementPolicyProvider::RefreshTaskExecute() { | |
273 DCHECK(refresh_task_); | |
274 refresh_task_ = NULL; | |
275 | |
276 switch (state_) { | |
277 case STATE_INITIALIZING: | |
278 token_fetcher_->StartFetching(); | |
279 return; | |
280 case STATE_TOKEN_VALID: | |
281 case STATE_POLICY_VALID: | |
282 case STATE_POLICY_ERROR: | |
283 SendPolicyRequest(); | |
284 return; | |
285 case STATE_UNMANAGED: | |
286 case STATE_TOKEN_ERROR: | |
287 case STATE_TOKEN_RESET: | |
288 token_fetcher_->Restart(); | |
289 return; | |
290 } | |
291 | |
292 NOTREACHED() << "Unhandled state"; | |
293 } | |
294 | |
295 void DeviceManagementPolicyProvider::CancelRefreshTask() { | |
296 if (refresh_task_) { | |
297 refresh_task_->Cancel(); | |
298 refresh_task_ = NULL; | |
299 } | |
300 } | |
301 | |
302 void DeviceManagementPolicyProvider::NotifyCloudPolicyUpdate() { | |
303 FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer, | |
304 observer_list_, | |
305 OnUpdatePolicy()); | |
306 } | |
307 | |
308 FilePath DeviceManagementPolicyProvider::GetTokenPath() { | |
309 return storage_dir_.Append(kDeviceTokenFilename); | |
310 } | |
311 | |
312 void DeviceManagementPolicyProvider::SetDeviceTokenFetcher( | |
313 DeviceTokenFetcher* token_fetcher) { | |
314 registrar_.Init(token_fetcher); | |
315 registrar_.AddObserver(this); | |
316 token_fetcher_ = token_fetcher; | |
317 } | |
318 | |
319 void DeviceManagementPolicyProvider::SetState( | |
320 DeviceManagementPolicyProvider::ProviderState new_state) { | |
321 state_ = new_state; | |
322 | |
323 // If this state transition completes the initial policy fetch, let the | |
324 // observers now. | |
325 if (!initial_fetch_done_ && | |
326 new_state != STATE_INITIALIZING && | |
327 new_state != STATE_TOKEN_VALID) { | |
328 initial_fetch_done_ = true; | |
329 NotifyCloudPolicyUpdate(); | |
330 } | |
331 | |
332 base::Time now(base::Time::NowFromSystemTime()); | |
333 base::Time refresh_at; | |
334 base::Time last_refresh(cache_->last_policy_refresh_time()); | |
335 if (last_refresh.is_null()) | |
336 last_refresh = now; | |
337 | |
338 // Determine when to take the next step. | |
339 switch (state_) { | |
340 case STATE_INITIALIZING: | |
341 refresh_at = now; | |
342 break; | |
343 case STATE_TOKEN_VALID: | |
344 effective_token_fetch_error_delay_ms_ = token_fetch_error_delay_ms_; | |
345 refresh_at = now; | |
346 break; | |
347 case STATE_TOKEN_RESET: | |
348 refresh_at = now; | |
349 break; | |
350 case STATE_UNMANAGED: | |
351 refresh_at = last_refresh + | |
352 base::TimeDelta::FromMilliseconds(unmanaged_device_refresh_rate_ms_); | |
353 break; | |
354 case STATE_POLICY_VALID: | |
355 effective_policy_refresh_error_delay_ms_ = policy_refresh_error_delay_ms_; | |
356 refresh_at = | |
357 last_refresh + base::TimeDelta::FromMilliseconds(GetRefreshDelay()); | |
358 break; | |
359 case STATE_TOKEN_ERROR: | |
360 refresh_at = now + base::TimeDelta::FromMilliseconds( | |
361 effective_token_fetch_error_delay_ms_); | |
362 effective_token_fetch_error_delay_ms_ *= 2; | |
363 if (effective_token_fetch_error_delay_ms_ > policy_refresh_rate_ms_) | |
364 effective_token_fetch_error_delay_ms_ = policy_refresh_rate_ms_; | |
365 break; | |
366 case STATE_POLICY_ERROR: | |
367 refresh_at = now + base::TimeDelta::FromMilliseconds( | |
368 effective_policy_refresh_error_delay_ms_); | |
369 effective_policy_refresh_error_delay_ms_ *= 2; | |
370 if (effective_policy_refresh_error_delay_ms_ > policy_refresh_rate_ms_) | |
371 effective_policy_refresh_error_delay_ms_ = policy_refresh_rate_ms_; | |
372 break; | |
373 } | |
374 | |
375 // Update the refresh task. | |
376 CancelRefreshTask(); | |
377 if (!refresh_at.is_null()) { | |
378 refresh_task_ = new RefreshTask(this); | |
379 int64 delay = std::max<int64>((refresh_at - now).InMilliseconds(), 0); | |
380 BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE, refresh_task_, | |
381 delay); | |
382 } | |
383 } | |
384 | |
385 int64 DeviceManagementPolicyProvider::GetRefreshDelay() { | |
386 int64 deviation = (policy_refresh_deviation_factor_percent_ * | |
387 policy_refresh_rate_ms_) / 100; | |
388 deviation = std::min(deviation, policy_refresh_deviation_max_ms_); | |
389 return policy_refresh_rate_ms_ - base::RandGenerator(deviation + 1); | |
390 } | |
391 | |
392 bool DeviceManagementPolicyProvider::TokenAvailable() const { | |
393 return state_ == STATE_TOKEN_VALID || | |
394 state_ == STATE_POLICY_VALID || | |
395 state_ == STATE_POLICY_ERROR; | |
396 } | |
397 | |
398 // static | |
399 std::string DeviceManagementPolicyProvider::GetDeviceManagementURL() { | |
400 return CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | |
401 switches::kDeviceManagementUrl); | |
402 } | |
403 | |
404 // static | |
405 FilePath DeviceManagementPolicyProvider::GetOrCreateDeviceManagementDir( | |
406 const FilePath& user_data_dir) { | |
407 const FilePath device_management_dir = user_data_dir.Append( | |
408 FILE_PATH_LITERAL("Device Management")); | |
409 if (!file_util::DirectoryExists(device_management_dir)) { | |
410 if (!file_util::CreateDirectory(device_management_dir)) | |
411 NOTREACHED(); | |
412 } | |
413 return device_management_dir; | |
414 } | |
415 | |
416 } // namespace policy | |
OLD | NEW |