OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 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_controller.h" | 5 #include "chrome/browser/policy/cloud_policy_controller.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
13 #include "base/rand_util.h" | 13 #include "base/rand_util.h" |
14 #include "base/string_util.h" | 14 #include "base/string_util.h" |
15 #include "base/time.h" | 15 #include "base/time.h" |
16 #include "chrome/browser/policy/cloud_policy_cache_base.h" | 16 #include "chrome/browser/policy/cloud_policy_cache_base.h" |
17 #include "chrome/browser/policy/cloud_policy_constants.h" | |
17 #include "chrome/browser/policy/cloud_policy_subsystem.h" | 18 #include "chrome/browser/policy/cloud_policy_subsystem.h" |
18 #include "chrome/browser/policy/delayed_work_scheduler.h" | 19 #include "chrome/browser/policy/delayed_work_scheduler.h" |
19 #include "chrome/browser/policy/device_management_service.h" | 20 #include "chrome/browser/policy/device_management_service.h" |
20 #include "chrome/browser/policy/device_token_fetcher.h" | 21 #include "chrome/browser/policy/device_token_fetcher.h" |
21 #include "chrome/browser/policy/enterprise_metrics.h" | 22 #include "chrome/browser/policy/enterprise_metrics.h" |
22 #include "chrome/browser/policy/policy_notifier.h" | 23 #include "chrome/browser/policy/policy_notifier.h" |
23 #include "chrome/browser/policy/proto/device_management_constants.h" | |
24 #include "chrome/common/guid.h" | 24 #include "chrome/common/guid.h" |
25 | 25 |
26 namespace { | 26 namespace { |
27 | 27 |
28 // The maximum ratio in percent of the policy refresh rate we use for adjusting | 28 // The maximum ratio in percent of the policy refresh rate we use for adjusting |
29 // the policy refresh time instant. The rationale is to avoid load spikes from | 29 // the policy refresh time instant. The rationale is to avoid load spikes from |
30 // many devices that were set up in sync for some reason. | 30 // many devices that were set up in sync for some reason. |
31 const int kPolicyRefreshDeviationFactorPercent = 10; | 31 const int kPolicyRefreshDeviationFactorPercent = 10; |
32 // Maximum deviation we are willing to accept. | 32 // Maximum deviation we are willing to accept. |
33 const int64 kPolicyRefreshDeviationMaxInMilliseconds = 30 * 60 * 1000; | 33 const int64 kPolicyRefreshDeviationMaxInMilliseconds = 30 * 60 * 1000; |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
116 // The controller doesn't have enough material to start a token fetch, | 116 // The controller doesn't have enough material to start a token fetch, |
117 // but observers of the cache are waiting for the refresh. | 117 // but observers of the cache are waiting for the refresh. |
118 SetState(STATE_TOKEN_UNMANAGED); | 118 SetState(STATE_TOKEN_UNMANAGED); |
119 } | 119 } |
120 } else { | 120 } else { |
121 // The token is valid, so the next step is to fetch policy. | 121 // The token is valid, so the next step is to fetch policy. |
122 SetState(STATE_TOKEN_VALID); | 122 SetState(STATE_TOKEN_VALID); |
123 } | 123 } |
124 } | 124 } |
125 | 125 |
126 void CloudPolicyController::HandlePolicyResponse( | 126 void CloudPolicyController::OnPolicyFetchCompleted( |
127 const em::DevicePolicyResponse& response) { | 127 DeviceManagementStatus status, |
128 if (response.response_size() > 0) { | 128 const em::DeviceManagementResponse& response) { |
129 if (response.response_size() > 1) { | 129 if (status == DM_STATUS_SUCCESS && !response.has_policy_response()) { |
130 LOG(WARNING) << "More than one policy in the response of the device " | 130 // Handled below. |
131 << "management server, discarding."; | 131 status = DM_STATUS_RESPONSE_DECODING_ERROR; |
132 } | |
133 | |
134 switch (status) { | |
135 case DM_STATUS_SUCCESS: { | |
136 const em::DevicePolicyResponse& policy_response( | |
137 response.policy_response()); | |
138 if (policy_response.response_size() > 0) { | |
139 if (policy_response.response_size() > 1) { | |
140 LOG(WARNING) << "More than one policy in the response of the device " | |
141 << "management server, discarding."; | |
142 } | |
143 const em::PolicyFetchResponse& fetch_response( | |
144 policy_response.response(0)); | |
145 if (!fetch_response.has_error_code() || | |
146 fetch_response.error_code() == dm_protocol::POLICY_FETCH_SUCCESS) { | |
147 cache_->SetPolicy(fetch_response); | |
148 SetState(STATE_POLICY_VALID); | |
149 } else { | |
150 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, | |
151 kMetricPolicyFetchBadResponse, | |
152 kMetricPolicySize); | |
153 SetState(STATE_POLICY_UNAVAILABLE); | |
154 } | |
155 } else { | |
156 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyFetchBadResponse, | |
157 kMetricPolicySize); | |
158 SetState(STATE_POLICY_UNAVAILABLE); | |
159 } | |
160 return; | |
132 } | 161 } |
133 if (!response.response(0).has_error_code() || | 162 case DM_STATUS_SERVICE_DEVICE_NOT_FOUND: |
134 response.response(0).error_code() == | 163 case DM_STATUS_SERVICE_DEVICE_ID_CONFLICT: |
135 DeviceManagementBackend::kPolicyFetchSuccess) { | 164 case DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID: { |
136 cache_->SetPolicy(response.response(0)); | |
137 SetState(STATE_POLICY_VALID); | |
138 } else { | |
139 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyFetchBadResponse, | |
140 kMetricPolicySize); | |
141 SetState(STATE_POLICY_UNAVAILABLE); | |
142 } | |
143 } else { | |
144 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyFetchBadResponse, | |
145 kMetricPolicySize); | |
146 SetState(STATE_POLICY_UNAVAILABLE); | |
147 } | |
148 } | |
149 | |
150 void CloudPolicyController::OnError(DeviceManagementBackend::ErrorCode code) { | |
151 switch (code) { | |
152 case DeviceManagementBackend::kErrorServiceDeviceNotFound: | |
153 case DeviceManagementBackend::kErrorServiceDeviceIdConflict: | |
154 case DeviceManagementBackend::kErrorServiceManagementTokenInvalid: { | |
155 LOG(WARNING) << "The device token was either invalid or unknown to the " | 165 LOG(WARNING) << "The device token was either invalid or unknown to the " |
156 << "device manager, re-registering device."; | 166 << "device manager, re-registering device."; |
157 // Will retry fetching a token but gracefully backing off. | 167 // Will retry fetching a token but gracefully backing off. |
158 SetState(STATE_TOKEN_ERROR); | 168 SetState(STATE_TOKEN_ERROR); |
159 return; | 169 return; |
160 } | 170 } |
161 case DeviceManagementBackend::kErrorServiceInvalidSerialNumber: { | 171 case DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER: { |
162 VLOG(1) << "The device is no longer enlisted for the domain."; | 172 VLOG(1) << "The device is no longer enlisted for the domain."; |
163 token_fetcher_->SetSerialNumberInvalidState(); | 173 token_fetcher_->SetSerialNumberInvalidState(); |
164 SetState(STATE_TOKEN_ERROR); | 174 SetState(STATE_TOKEN_ERROR); |
165 return; | 175 return; |
166 } | 176 } |
167 case DeviceManagementBackend::kErrorServiceManagementNotSupported: { | 177 case DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED: { |
168 VLOG(1) << "The device is no longer managed."; | 178 VLOG(1) << "The device is no longer managed."; |
169 token_fetcher_->SetUnmanagedState(); | 179 token_fetcher_->SetUnmanagedState(); |
170 SetState(STATE_TOKEN_UNMANAGED); | 180 SetState(STATE_TOKEN_UNMANAGED); |
171 return; | 181 return; |
172 } | 182 } |
173 case DeviceManagementBackend::kErrorServicePolicyNotFound: | 183 case DM_STATUS_SERVICE_POLICY_NOT_FOUND: |
174 case DeviceManagementBackend::kErrorRequestInvalid: | 184 case DM_STATUS_REQUEST_INVALID: |
175 case DeviceManagementBackend::kErrorServiceActivationPending: | 185 case DM_STATUS_SERVICE_ACTIVATION_PENDING: |
176 case DeviceManagementBackend::kErrorResponseDecoding: | 186 case DM_STATUS_RESPONSE_DECODING_ERROR: |
177 case DeviceManagementBackend::kErrorHttpStatus: { | 187 case DM_STATUS_HTTP_STATUS_ERROR: { |
178 VLOG(1) << "An error in the communication with the policy server occurred" | 188 VLOG(1) << "An error in the communication with the policy server occurred" |
179 << ", will retry in a few hours."; | 189 << ", will retry in a few hours."; |
180 SetState(STATE_POLICY_UNAVAILABLE); | 190 SetState(STATE_POLICY_UNAVAILABLE); |
181 return; | 191 return; |
182 } | 192 } |
183 case DeviceManagementBackend::kErrorRequestFailed: | 193 case DM_STATUS_REQUEST_FAILED: |
184 case DeviceManagementBackend::kErrorTemporaryUnavailable: { | 194 case DM_STATUS_TEMPORARY_UNAVAILABLE: { |
Joao da Silva
2012/01/03 08:19:02
Nit: curlies are not necessary in these cases; I d
Mattias Nissler (ping if slow)
2012/01/03 10:02:45
Done.
| |
185 VLOG(1) << "A temporary error in the communication with the policy server" | 195 VLOG(1) << "A temporary error in the communication with the policy server" |
186 << " occurred."; | 196 << " occurred."; |
187 // Will retry last operation but gracefully backing off. | 197 // Will retry last operation but gracefully backing off. |
188 SetState(STATE_POLICY_ERROR); | 198 SetState(STATE_POLICY_ERROR); |
189 return; | 199 return; |
190 } | 200 } |
191 } | 201 } |
192 | 202 |
193 NOTREACHED(); | 203 NOTREACHED(); |
194 SetState(STATE_POLICY_ERROR); | 204 SetState(STATE_POLICY_ERROR); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
272 token_fetcher_->FetchToken(); | 282 token_fetcher_->FetchToken(); |
273 } else { | 283 } else { |
274 SetState(STATE_TOKEN_UNMANAGED); | 284 SetState(STATE_TOKEN_UNMANAGED); |
275 } | 285 } |
276 } else { | 286 } else { |
277 VLOG(1) << "Not ready to fetch DMToken yet, will try again later."; | 287 VLOG(1) << "Not ready to fetch DMToken yet, will try again later."; |
278 } | 288 } |
279 } | 289 } |
280 | 290 |
281 void CloudPolicyController::SendPolicyRequest() { | 291 void CloudPolicyController::SendPolicyRequest() { |
282 backend_.reset(service_->CreateBackend()); | |
283 DCHECK(!data_store_->device_token().empty()); | 292 DCHECK(!data_store_->device_token().empty()); |
284 em::DevicePolicyRequest policy_request; | 293 request_job_.reset( |
285 em::PolicyFetchRequest* fetch_request = policy_request.add_request(); | 294 service_->CreateJob(DeviceManagementRequestJob::TYPE_POLICY_FETCH)); |
295 request_job_->SetDMToken(data_store_->device_token()); | |
296 request_job_->SetClientID(data_store_->device_id()); | |
297 request_job_->SetUserAffiliation(data_store_->user_affiliation()); | |
298 | |
299 em::DeviceManagementRequest* request = request_job_->GetRequest(); | |
300 em::PolicyFetchRequest* fetch_request = | |
301 request->mutable_policy_request()->add_request(); | |
286 em::DeviceStatusReportRequest device_status; | 302 em::DeviceStatusReportRequest device_status; |
287 fetch_request->set_signature_type(em::PolicyFetchRequest::SHA1_RSA); | 303 fetch_request->set_signature_type(em::PolicyFetchRequest::SHA1_RSA); |
288 fetch_request->set_policy_type(data_store_->policy_type()); | 304 fetch_request->set_policy_type(data_store_->policy_type()); |
289 if (cache_->machine_id_missing() && !data_store_->machine_id().empty()) | 305 if (cache_->machine_id_missing() && !data_store_->machine_id().empty()) |
290 fetch_request->set_machine_id(data_store_->machine_id()); | 306 fetch_request->set_machine_id(data_store_->machine_id()); |
291 if (!cache_->is_unmanaged() && | 307 if (!cache_->is_unmanaged() && |
292 !cache_->last_policy_refresh_time().is_null()) { | 308 !cache_->last_policy_refresh_time().is_null()) { |
293 base::TimeDelta timestamp = | 309 base::TimeDelta timestamp = |
294 cache_->last_policy_refresh_time() - base::Time::UnixEpoch(); | 310 cache_->last_policy_refresh_time() - base::Time::UnixEpoch(); |
295 fetch_request->set_timestamp(timestamp.InMilliseconds()); | 311 fetch_request->set_timestamp(timestamp.InMilliseconds()); |
296 } | 312 } |
297 int key_version = 0; | 313 int key_version = 0; |
298 if (cache_->GetPublicKeyVersion(&key_version)) | 314 if (cache_->GetPublicKeyVersion(&key_version)) |
299 fetch_request->set_public_key_version(key_version); | 315 fetch_request->set_public_key_version(key_version); |
300 | 316 |
301 #if defined(OS_CHROMEOS) | 317 #if defined(OS_CHROMEOS) |
302 if (data_store_->device_status_collector()) | 318 if (data_store_->device_status_collector()) { |
303 data_store_->device_status_collector()->GetStatus(&device_status); | 319 data_store_->device_status_collector()->GetStatus( |
320 request->mutable_device_status_report_request()); | |
321 } | |
304 #endif | 322 #endif |
305 | 323 |
306 backend_->ProcessPolicyRequest(data_store_->device_token(), | 324 request_job_->Start(base::Bind(&CloudPolicyController::OnPolicyFetchCompleted, |
307 data_store_->device_id(), | 325 base::Unretained(this))); |
308 data_store_->user_affiliation(), | |
309 policy_request, &device_status, this); | |
310 } | 326 } |
311 | 327 |
312 void CloudPolicyController::DoWork() { | 328 void CloudPolicyController::DoWork() { |
313 switch (state_) { | 329 switch (state_) { |
314 case STATE_TOKEN_UNAVAILABLE: | 330 case STATE_TOKEN_UNAVAILABLE: |
315 case STATE_TOKEN_ERROR: | 331 case STATE_TOKEN_ERROR: |
316 FetchToken(); | 332 FetchToken(); |
317 return; | 333 return; |
318 case STATE_TOKEN_VALID: | 334 case STATE_TOKEN_VALID: |
319 case STATE_POLICY_VALID: | 335 case STATE_POLICY_VALID: |
320 case STATE_POLICY_ERROR: | 336 case STATE_POLICY_ERROR: |
321 case STATE_POLICY_UNAVAILABLE: | 337 case STATE_POLICY_UNAVAILABLE: |
322 SendPolicyRequest(); | 338 SendPolicyRequest(); |
323 return; | 339 return; |
324 case STATE_TOKEN_UNMANAGED: | 340 case STATE_TOKEN_UNMANAGED: |
325 return; | 341 return; |
326 } | 342 } |
327 | 343 |
328 NOTREACHED() << "Unhandled state" << state_; | 344 NOTREACHED() << "Unhandled state" << state_; |
329 } | 345 } |
330 | 346 |
331 void CloudPolicyController::SetState( | 347 void CloudPolicyController::SetState( |
332 CloudPolicyController::ControllerState new_state) { | 348 CloudPolicyController::ControllerState new_state) { |
333 state_ = new_state; | 349 state_ = new_state; |
334 | 350 |
335 backend_.reset(); // Stop any pending requests. | 351 request_job_.reset(); // Stop any pending requests. |
336 | 352 |
337 base::Time now(base::Time::NowFromSystemTime()); | 353 base::Time now(base::Time::NowFromSystemTime()); |
338 base::Time refresh_at; | 354 base::Time refresh_at; |
339 base::Time last_refresh(cache_->last_policy_refresh_time()); | 355 base::Time last_refresh(cache_->last_policy_refresh_time()); |
340 if (last_refresh.is_null()) | 356 if (last_refresh.is_null()) |
341 last_refresh = now; | 357 last_refresh = now; |
342 | 358 |
343 // Determine when to take the next step. | 359 // Determine when to take the next step. |
344 bool inform_notifier_done = false; | 360 bool inform_notifier_done = false; |
345 switch (state_) { | 361 switch (state_) { |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
413 } | 429 } |
414 | 430 |
415 int64 CloudPolicyController::GetRefreshDelay() { | 431 int64 CloudPolicyController::GetRefreshDelay() { |
416 int64 deviation = (kPolicyRefreshDeviationFactorPercent * | 432 int64 deviation = (kPolicyRefreshDeviationFactorPercent * |
417 policy_refresh_rate_ms_) / 100; | 433 policy_refresh_rate_ms_) / 100; |
418 deviation = std::min(deviation, kPolicyRefreshDeviationMaxInMilliseconds); | 434 deviation = std::min(deviation, kPolicyRefreshDeviationMaxInMilliseconds); |
419 return policy_refresh_rate_ms_ - base::RandGenerator(deviation + 1); | 435 return policy_refresh_rate_ms_ - base::RandGenerator(deviation + 1); |
420 } | 436 } |
421 | 437 |
422 } // namespace policy | 438 } // namespace policy |
OLD | NEW |