| Index: chrome/browser/policy/cloud/cloud_policy_invalidator.cc
|
| diff --git a/chrome/browser/policy/cloud/cloud_policy_invalidator.cc b/chrome/browser/policy/cloud/cloud_policy_invalidator.cc
|
| index 17ede20e4c36cc333fb0a76c68f1d33867d70ced..751498c99fd362312dde6eadbf64cb2e47e3ab40 100644
|
| --- a/chrome/browser/policy/cloud/cloud_policy_invalidator.cc
|
| +++ b/chrome/browser/policy/cloud/cloud_policy_invalidator.cc
|
| @@ -42,7 +42,6 @@ CloudPolicyInvalidator::CloudPolicyInvalidator(
|
| invalid_(false),
|
| invalidation_version_(0),
|
| unknown_version_invalidation_count_(0),
|
| - ack_handle_(syncer::AckHandle::InvalidAckHandle()),
|
| weak_factory_(this),
|
| max_fetch_delay_(kMaxFetchDelayDefault),
|
| policy_hash_value_(0) {
|
| @@ -92,13 +91,22 @@ void CloudPolicyInvalidator::OnIncomingInvalidation(
|
| const syncer::ObjectIdInvalidationMap& invalidation_map) {
|
| DCHECK(state_ == STARTED);
|
| DCHECK(thread_checker_.CalledOnValidThread());
|
| - const syncer::ObjectIdInvalidationMap::const_iterator invalidation =
|
| - invalidation_map.find(object_id_);
|
| - if (invalidation == invalidation_map.end()) {
|
| +
|
| + const syncer::OrderedInvalidationList& list =
|
| + invalidation_map.ForObject(object_id_);
|
| + if (list.IsEmpty()) {
|
| NOTREACHED();
|
| return;
|
| }
|
| - HandleInvalidation(invalidation->second);
|
| +
|
| + // Acknowledge all except the invalidation with the highest version.
|
| + syncer::OrderedInvalidationList::const_reverse_iterator it = list.rbegin();
|
| + ++it;
|
| + for ( ; it != list.rend(); ++it) {
|
| + it->Acknowledge();
|
| + }
|
| +
|
| + HandleInvalidation(list.back());
|
| }
|
|
|
| void CloudPolicyInvalidator::OnCoreConnected(CloudPolicyCore* core) {}
|
| @@ -154,10 +162,12 @@ void CloudPolicyInvalidator::OnStoreError(CloudPolicyStore* store) {}
|
|
|
| void CloudPolicyInvalidator::HandleInvalidation(
|
| const syncer::Invalidation& invalidation) {
|
| - // The invalidation service may send an invalidation more than once if there
|
| - // is a delay in acknowledging it. Duplicate invalidations are ignored.
|
| - if (invalid_ && ack_handle_.Equals(invalidation.ack_handle))
|
| + // Ignore old invalidations.
|
| + if (invalid_ &&
|
| + !invalidation.IsUnknownVersion() &&
|
| + invalidation.GetVersion() <= invalidation_version_) {
|
| return;
|
| + }
|
|
|
| // If there is still a pending invalidation, acknowledge it, since we only
|
| // care about the latest invalidation.
|
| @@ -166,15 +176,16 @@ void CloudPolicyInvalidator::HandleInvalidation(
|
|
|
| // Update invalidation state.
|
| invalid_ = true;
|
| - ack_handle_ = invalidation.ack_handle;
|
| - invalidation_version_ = invalidation.version;
|
| -
|
| - // When an invalidation with unknown version is received, use negative
|
| - // numbers based on the number of such invalidations received. This
|
| - // ensures that the version numbers do not collide with "real" versions
|
| - // (which are positive) or previous invalidations with unknown version.
|
| - if (invalidation_version_ == syncer::Invalidation::kUnknownVersion)
|
| + invalidation_ = invalidation;
|
| + if (invalidation.IsUnknownVersion()) {
|
| + // When an invalidation with unknown version is received, use negative
|
| + // numbers based on the number of such invalidations received. This ensures
|
| + // that the version numbers do not collide with "real" versions (which are
|
| + // positive) or previous invalidations with unknown version.
|
| invalidation_version_ = -(++unknown_version_invalidation_count_);
|
| + } else {
|
| + invalidation_version_ = invalidation.GetVersion();
|
| + }
|
|
|
| // In order to prevent the cloud policy server from becoming overwhelmed when
|
| // a policy with many users is modified, delay for a random period of time
|
| @@ -184,11 +195,14 @@ void CloudPolicyInvalidator::HandleInvalidation(
|
| base::TimeDelta delay = base::TimeDelta::FromMilliseconds(
|
| base::RandInt(20, max_fetch_delay_));
|
|
|
| - // If there is a payload, the policy can be refreshed at any time, so set
|
| - // the version and payload on the client immediately. Otherwise, the refresh
|
| + std::string payload;
|
| + if (!invalidation.IsUnknownVersion())
|
| + payload = invalidation.GetPayload();
|
| +
|
| + // If there is a payload, the invalidate callback can run at any time, so set
|
| + // the version and payload on the client immediately. Otherwise, the callback
|
| // must only run after at least kMissingPayloadDelay minutes.
|
| - const std::string& payload = invalidation.payload;
|
| - if (!invalidation.payload.empty())
|
| + if (!payload.empty())
|
| core_->client()->SetInvalidationInfo(invalidation_version_, payload);
|
| else
|
| delay += base::TimeDelta::FromMinutes(kMissingPayloadDelay);
|
| @@ -317,8 +331,9 @@ void CloudPolicyInvalidator::AcknowledgeInvalidation() {
|
| DCHECK(invalid_);
|
| invalid_ = false;
|
| core_->client()->SetInvalidationInfo(0, std::string());
|
| - invalidation_service_->AcknowledgeInvalidation(object_id_, ack_handle_);
|
| - // Cancel any scheduled policy refreshes.
|
| + invalidation_.Acknowledge();
|
| + invalidation_ = syncer::Invalidation();
|
| + // Cancel any scheduled invalidate callbacks.
|
| weak_factory_.InvalidateWeakPtrs();
|
| }
|
|
|
|
|