| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/cloud_policy_invalidator.h" | 5 #include "chrome/browser/policy/cloud/cloud_policy_invalidator.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
| 9 #include "base/hash.h" | 9 #include "base/hash.h" |
| 10 #include "base/location.h" | 10 #include "base/location.h" |
| (...skipping 24 matching lines...) Expand all Loading... |
| 35 : state_(UNINITIALIZED), | 35 : state_(UNINITIALIZED), |
| 36 core_(core), | 36 core_(core), |
| 37 task_runner_(task_runner), | 37 task_runner_(task_runner), |
| 38 invalidation_service_(NULL), | 38 invalidation_service_(NULL), |
| 39 invalidations_enabled_(false), | 39 invalidations_enabled_(false), |
| 40 invalidation_service_enabled_(false), | 40 invalidation_service_enabled_(false), |
| 41 registered_timestamp_(0), | 41 registered_timestamp_(0), |
| 42 invalid_(false), | 42 invalid_(false), |
| 43 invalidation_version_(0), | 43 invalidation_version_(0), |
| 44 unknown_version_invalidation_count_(0), | 44 unknown_version_invalidation_count_(0), |
| 45 ack_handle_(syncer::AckHandle::InvalidAckHandle()), | |
| 46 weak_factory_(this), | 45 weak_factory_(this), |
| 47 max_fetch_delay_(kMaxFetchDelayDefault), | 46 max_fetch_delay_(kMaxFetchDelayDefault), |
| 48 policy_hash_value_(0) { | 47 policy_hash_value_(0) { |
| 49 DCHECK(core); | 48 DCHECK(core); |
| 50 DCHECK(task_runner.get()); | 49 DCHECK(task_runner.get()); |
| 51 } | 50 } |
| 52 | 51 |
| 53 CloudPolicyInvalidator::~CloudPolicyInvalidator() { | 52 CloudPolicyInvalidator::~CloudPolicyInvalidator() { |
| 54 DCHECK(state_ == SHUT_DOWN); | 53 DCHECK(state_ == SHUT_DOWN); |
| 55 } | 54 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 85 DCHECK(state_ == STARTED); | 84 DCHECK(state_ == STARTED); |
| 86 DCHECK(thread_checker_.CalledOnValidThread()); | 85 DCHECK(thread_checker_.CalledOnValidThread()); |
| 87 invalidation_service_enabled_ = state == syncer::INVALIDATIONS_ENABLED; | 86 invalidation_service_enabled_ = state == syncer::INVALIDATIONS_ENABLED; |
| 88 UpdateInvalidationsEnabled(); | 87 UpdateInvalidationsEnabled(); |
| 89 } | 88 } |
| 90 | 89 |
| 91 void CloudPolicyInvalidator::OnIncomingInvalidation( | 90 void CloudPolicyInvalidator::OnIncomingInvalidation( |
| 92 const syncer::ObjectIdInvalidationMap& invalidation_map) { | 91 const syncer::ObjectIdInvalidationMap& invalidation_map) { |
| 93 DCHECK(state_ == STARTED); | 92 DCHECK(state_ == STARTED); |
| 94 DCHECK(thread_checker_.CalledOnValidThread()); | 93 DCHECK(thread_checker_.CalledOnValidThread()); |
| 95 const syncer::ObjectIdInvalidationMap::const_iterator invalidation = | 94 |
| 96 invalidation_map.find(object_id_); | 95 const syncer::OrderedInvalidationList& list = |
| 97 if (invalidation == invalidation_map.end()) { | 96 invalidation_map.ForObject(object_id_); |
| 97 if (list.IsEmpty()) { |
| 98 NOTREACHED(); | 98 NOTREACHED(); |
| 99 return; | 99 return; |
| 100 } | 100 } |
| 101 HandleInvalidation(invalidation->second); | 101 |
| 102 // Acknowledge all except the invalidation with the highest version. |
| 103 syncer::OrderedInvalidationList::const_reverse_iterator it = list.rbegin(); |
| 104 ++it; |
| 105 for ( ; it != list.rend(); ++it) { |
| 106 it->Acknowledge(); |
| 107 } |
| 108 |
| 109 HandleInvalidation(list.back()); |
| 102 } | 110 } |
| 103 | 111 |
| 104 void CloudPolicyInvalidator::OnCoreConnected(CloudPolicyCore* core) {} | 112 void CloudPolicyInvalidator::OnCoreConnected(CloudPolicyCore* core) {} |
| 105 | 113 |
| 106 void CloudPolicyInvalidator::OnRefreshSchedulerStarted(CloudPolicyCore* core) { | 114 void CloudPolicyInvalidator::OnRefreshSchedulerStarted(CloudPolicyCore* core) { |
| 107 DCHECK(state_ == STOPPED); | 115 DCHECK(state_ == STOPPED); |
| 108 DCHECK(thread_checker_.CalledOnValidThread()); | 116 DCHECK(thread_checker_.CalledOnValidThread()); |
| 109 state_ = STARTED; | 117 state_ = STARTED; |
| 110 OnStoreLoaded(core_->store()); | 118 OnStoreLoaded(core_->store()); |
| 111 core_->store()->AddObserver(this); | 119 core_->store()->AddObserver(this); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 147 } | 155 } |
| 148 | 156 |
| 149 UpdateRegistration(store->policy()); | 157 UpdateRegistration(store->policy()); |
| 150 UpdateMaxFetchDelay(store->policy_map()); | 158 UpdateMaxFetchDelay(store->policy_map()); |
| 151 } | 159 } |
| 152 | 160 |
| 153 void CloudPolicyInvalidator::OnStoreError(CloudPolicyStore* store) {} | 161 void CloudPolicyInvalidator::OnStoreError(CloudPolicyStore* store) {} |
| 154 | 162 |
| 155 void CloudPolicyInvalidator::HandleInvalidation( | 163 void CloudPolicyInvalidator::HandleInvalidation( |
| 156 const syncer::Invalidation& invalidation) { | 164 const syncer::Invalidation& invalidation) { |
| 157 // The invalidation service may send an invalidation more than once if there | 165 // Ignore old invalidations. |
| 158 // is a delay in acknowledging it. Duplicate invalidations are ignored. | 166 if (invalid_ && |
| 159 if (invalid_ && ack_handle_.Equals(invalidation.ack_handle)) | 167 !invalidation.IsUnknownVersion() && |
| 168 invalidation.GetVersion() <= invalidation_version_) { |
| 160 return; | 169 return; |
| 170 } |
| 161 | 171 |
| 162 // If there is still a pending invalidation, acknowledge it, since we only | 172 // If there is still a pending invalidation, acknowledge it, since we only |
| 163 // care about the latest invalidation. | 173 // care about the latest invalidation. |
| 164 if (invalid_) | 174 if (invalid_) |
| 165 AcknowledgeInvalidation(); | 175 AcknowledgeInvalidation(); |
| 166 | 176 |
| 167 // Update invalidation state. | 177 // Update invalidation state. |
| 168 invalid_ = true; | 178 invalid_ = true; |
| 169 ack_handle_ = invalidation.ack_handle; | 179 invalidation_ = invalidation; |
| 170 invalidation_version_ = invalidation.version; | 180 if (invalidation.IsUnknownVersion()) { |
| 171 | 181 // When an invalidation with unknown version is received, use negative |
| 172 // When an invalidation with unknown version is received, use negative | 182 // numbers based on the number of such invalidations received. This ensures |
| 173 // numbers based on the number of such invalidations received. This | 183 // that the version numbers do not collide with "real" versions (which are |
| 174 // ensures that the version numbers do not collide with "real" versions | 184 // positive) or previous invalidations with unknown version. |
| 175 // (which are positive) or previous invalidations with unknown version. | |
| 176 if (invalidation_version_ == syncer::Invalidation::kUnknownVersion) | |
| 177 invalidation_version_ = -(++unknown_version_invalidation_count_); | 185 invalidation_version_ = -(++unknown_version_invalidation_count_); |
| 186 } else { |
| 187 invalidation_version_ = invalidation.GetVersion(); |
| 188 } |
| 178 | 189 |
| 179 // In order to prevent the cloud policy server from becoming overwhelmed when | 190 // In order to prevent the cloud policy server from becoming overwhelmed when |
| 180 // a policy with many users is modified, delay for a random period of time | 191 // a policy with many users is modified, delay for a random period of time |
| 181 // before fetching the policy. Delay for at least 20ms so that if multiple | 192 // before fetching the policy. Delay for at least 20ms so that if multiple |
| 182 // invalidations are received in quick succession, only one fetch will be | 193 // invalidations are received in quick succession, only one fetch will be |
| 183 // performed. | 194 // performed. |
| 184 base::TimeDelta delay = base::TimeDelta::FromMilliseconds( | 195 base::TimeDelta delay = base::TimeDelta::FromMilliseconds( |
| 185 base::RandInt(20, max_fetch_delay_)); | 196 base::RandInt(20, max_fetch_delay_)); |
| 186 | 197 |
| 187 // If there is a payload, the policy can be refreshed at any time, so set | 198 std::string payload; |
| 188 // the version and payload on the client immediately. Otherwise, the refresh | 199 if (!invalidation.IsUnknownVersion()) |
| 200 payload = invalidation.GetPayload(); |
| 201 |
| 202 // If there is a payload, the invalidate callback can run at any time, so set |
| 203 // the version and payload on the client immediately. Otherwise, the callback |
| 189 // must only run after at least kMissingPayloadDelay minutes. | 204 // must only run after at least kMissingPayloadDelay minutes. |
| 190 const std::string& payload = invalidation.payload; | 205 if (!payload.empty()) |
| 191 if (!invalidation.payload.empty()) | |
| 192 core_->client()->SetInvalidationInfo(invalidation_version_, payload); | 206 core_->client()->SetInvalidationInfo(invalidation_version_, payload); |
| 193 else | 207 else |
| 194 delay += base::TimeDelta::FromMinutes(kMissingPayloadDelay); | 208 delay += base::TimeDelta::FromMinutes(kMissingPayloadDelay); |
| 195 | 209 |
| 196 // Schedule the policy to be refreshed. | 210 // Schedule the policy to be refreshed. |
| 197 task_runner_->PostDelayedTask( | 211 task_runner_->PostDelayedTask( |
| 198 FROM_HERE, | 212 FROM_HERE, |
| 199 base::Bind( | 213 base::Bind( |
| 200 &CloudPolicyInvalidator::RefreshPolicy, | 214 &CloudPolicyInvalidator::RefreshPolicy, |
| 201 weak_factory_.GetWeakPtr(), | 215 weak_factory_.GetWeakPtr(), |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 310 // the client yet, so set it now that the required time has elapsed. | 324 // the client yet, so set it now that the required time has elapsed. |
| 311 if (is_missing_payload) | 325 if (is_missing_payload) |
| 312 core_->client()->SetInvalidationInfo(invalidation_version_, std::string()); | 326 core_->client()->SetInvalidationInfo(invalidation_version_, std::string()); |
| 313 core_->refresh_scheduler()->RefreshSoon(); | 327 core_->refresh_scheduler()->RefreshSoon(); |
| 314 } | 328 } |
| 315 | 329 |
| 316 void CloudPolicyInvalidator::AcknowledgeInvalidation() { | 330 void CloudPolicyInvalidator::AcknowledgeInvalidation() { |
| 317 DCHECK(invalid_); | 331 DCHECK(invalid_); |
| 318 invalid_ = false; | 332 invalid_ = false; |
| 319 core_->client()->SetInvalidationInfo(0, std::string()); | 333 core_->client()->SetInvalidationInfo(0, std::string()); |
| 320 invalidation_service_->AcknowledgeInvalidation(object_id_, ack_handle_); | 334 invalidation_.Acknowledge(); |
| 321 // Cancel any scheduled policy refreshes. | 335 invalidation_ = syncer::Invalidation(); |
| 336 // Cancel any scheduled invalidate callbacks. |
| 322 weak_factory_.InvalidateWeakPtrs(); | 337 weak_factory_.InvalidateWeakPtrs(); |
| 323 } | 338 } |
| 324 | 339 |
| 325 bool CloudPolicyInvalidator::IsPolicyChanged( | 340 bool CloudPolicyInvalidator::IsPolicyChanged( |
| 326 const enterprise_management::PolicyData* policy) { | 341 const enterprise_management::PolicyData* policy) { |
| 327 // Determine if the policy changed by comparing its hash value to the | 342 // Determine if the policy changed by comparing its hash value to the |
| 328 // previous policy's hash value. | 343 // previous policy's hash value. |
| 329 uint32 new_hash_value = 0; | 344 uint32 new_hash_value = 0; |
| 330 if (policy && policy->has_policy_value()) | 345 if (policy && policy->has_policy_value()) |
| 331 new_hash_value = base::Hash(policy->policy_value()); | 346 new_hash_value = base::Hash(policy->policy_value()); |
| 332 bool changed = new_hash_value != policy_hash_value_; | 347 bool changed = new_hash_value != policy_hash_value_; |
| 333 policy_hash_value_ = new_hash_value; | 348 policy_hash_value_ = new_hash_value; |
| 334 return changed; | 349 return changed; |
| 335 } | 350 } |
| 336 | 351 |
| 337 int CloudPolicyInvalidator::GetPolicyRefreshMetric(bool policy_changed) { | 352 int CloudPolicyInvalidator::GetPolicyRefreshMetric(bool policy_changed) { |
| 338 if (policy_changed) { | 353 if (policy_changed) { |
| 339 if (invalid_) | 354 if (invalid_) |
| 340 return METRIC_POLICY_REFRESH_INVALIDATED_CHANGED; | 355 return METRIC_POLICY_REFRESH_INVALIDATED_CHANGED; |
| 341 if (invalidations_enabled_) | 356 if (invalidations_enabled_) |
| 342 return METRIC_POLICY_REFRESH_CHANGED; | 357 return METRIC_POLICY_REFRESH_CHANGED; |
| 343 return METRIC_POLICY_REFRESH_CHANGED_NO_INVALIDATIONS; | 358 return METRIC_POLICY_REFRESH_CHANGED_NO_INVALIDATIONS; |
| 344 } | 359 } |
| 345 if (invalid_) | 360 if (invalid_) |
| 346 return METRIC_POLICY_REFRESH_INVALIDATED_UNCHANGED; | 361 return METRIC_POLICY_REFRESH_INVALIDATED_UNCHANGED; |
| 347 return METRIC_POLICY_REFRESH_UNCHANGED; | 362 return METRIC_POLICY_REFRESH_UNCHANGED; |
| 348 } | 363 } |
| 349 | 364 |
| 350 } // namespace policy | 365 } // namespace policy |
| OLD | NEW |