1a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// found in the LICENSE file.
4a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
5a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "chrome/browser/policy/cloud/cloud_policy_invalidator.h"
6a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
7a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/bind.h"
8a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/command_line.h"
9a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/location.h"
10a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/metrics/histogram.h"
11a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/rand_util.h"
12a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/sequenced_task_runner.h"
13a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
14a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/time/time.h"
15a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/values.h"
16a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "chrome/browser/invalidation/invalidation_service.h"
17a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "chrome/browser/invalidation/invalidation_service_factory.h"
18a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "chrome/browser/policy/cloud/enterprise_metrics.h"
19a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "chrome/common/chrome_switches.h"
20a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "policy/policy_constants.h"
21a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "sync/notifier/object_id_invalidation_map.h"
22a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
23a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)namespace policy {
24a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
25a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const int CloudPolicyInvalidator::kMissingPayloadDelay = 5;
26a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const int CloudPolicyInvalidator::kMaxFetchDelayDefault = 5000;
27a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const int CloudPolicyInvalidator::kMaxFetchDelayMin = 1000;
28a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const int CloudPolicyInvalidator::kMaxFetchDelayMax = 300000;
29a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
30a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)CloudPolicyInvalidator::CloudPolicyInvalidator(
31a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    CloudPolicyInvalidationHandler* invalidation_handler,
32a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    CloudPolicyStore* store,
33a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const scoped_refptr<base::SequencedTaskRunner>& task_runner)
34a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    : invalidation_handler_(invalidation_handler),
35a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      store_(store),
36a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      task_runner_(task_runner),
37a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      profile_(NULL),
38a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      invalidation_service_(NULL),
39a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      invalidations_enabled_(false),
40a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      invalidation_service_enabled_(false),
41a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      registered_timestamp_(0),
42a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      invalid_(false),
43a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      invalidation_version_(0),
44a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      unknown_version_invalidation_count_(0),
45a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      ack_handle_(syncer::AckHandle::InvalidAckHandle()),
46a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      weak_factory_(this),
47a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      max_fetch_delay_(kMaxFetchDelayDefault) {
48a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(invalidation_handler);
49a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(store);
50a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(task_runner.get());
51a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(!IsInitialized());
52a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
53a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
54a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)CloudPolicyInvalidator::~CloudPolicyInvalidator() {}
55a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
56a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void CloudPolicyInvalidator::InitializeWithProfile(Profile* profile) {
57a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(!IsInitialized());
58a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(profile);
59a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  profile_ = profile;
60a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  Initialize();
61a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
62a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
63a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void CloudPolicyInvalidator::InitializeWithService(
64a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    invalidation::InvalidationService* invalidation_service) {
65a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(!IsInitialized());
66a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(invalidation_service);
67a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  invalidation_service_ = invalidation_service;
68a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  Initialize();
69a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
70a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
71a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void CloudPolicyInvalidator::Shutdown() {
72a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (IsInitialized()) {
73a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (registered_timestamp_)
74a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      invalidation_service_->UnregisterInvalidationHandler(this);
75a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    store_->RemoveObserver(this);
76a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
77a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
78a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
79a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void CloudPolicyInvalidator::OnInvalidatorStateChange(
80a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    syncer::InvalidatorState state) {
81a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
82a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  invalidation_service_enabled_ = state == syncer::INVALIDATIONS_ENABLED;
83a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  UpdateInvalidationsEnabled();
84a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
85a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
86a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void CloudPolicyInvalidator::OnIncomingInvalidation(
87a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const syncer::ObjectIdInvalidationMap& invalidation_map) {
88a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
89a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const syncer::ObjectIdInvalidationMap::const_iterator invalidation =
90a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      invalidation_map.find(object_id_);
91a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (invalidation == invalidation_map.end()) {
92a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    NOTREACHED();
93a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return;
94a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
95a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  HandleInvalidation(invalidation->second);
96a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
97a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
98a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void CloudPolicyInvalidator::OnStoreLoaded(CloudPolicyStore* store) {
99a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(IsInitialized());
100a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
101a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (registered_timestamp_) {
102a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // Update the kMetricPolicyRefresh histogram. In some cases, this object can
103a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // be constructed during an OnStoreLoaded callback, which causes
104a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // OnStoreLoaded to be called twice at initialization time, so make sure
105a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // that the timestamp does not match the timestamp at which registration
106a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // occurred. We only measure changes which occur after registration.
107a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (!store->policy() || !store->policy()->has_timestamp() ||
108a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        store->policy()->timestamp() != registered_timestamp_) {
109a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      UMA_HISTOGRAM_ENUMERATION(
110a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          kMetricPolicyRefresh,
111a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          GetPolicyRefreshMetric(),
112a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          METRIC_POLICY_REFRESH_SIZE);
113a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    }
114a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
115a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // If the policy was invalid and the version stored matches the latest
116a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // invalidation version, acknowledge the latest invalidation.
117a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (invalid_ && store->invalidation_version() == invalidation_version_)
118a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      AcknowledgeInvalidation();
119a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
120a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
121a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  UpdateRegistration(store->policy());
122a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  UpdateMaxFetchDelay(store->policy_map());
123a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
124a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
125a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void CloudPolicyInvalidator::OnStoreError(CloudPolicyStore* store) {}
126a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
127a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)base::WeakPtr<CloudPolicyInvalidator> CloudPolicyInvalidator::GetWeakPtr() {
128a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(!IsInitialized());
129a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return weak_factory_.GetWeakPtr();
130a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
131a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
132a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void CloudPolicyInvalidator::Initialize() {
133a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  OnStoreLoaded(store_);
134a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  store_->AddObserver(this);
135a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
136a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
137a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool CloudPolicyInvalidator::IsInitialized() {
138a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Could have been initialized with a profile or invalidation service.
139a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return profile_ || invalidation_service_;
140a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
141a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
142a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void CloudPolicyInvalidator::HandleInvalidation(
143a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const syncer::Invalidation& invalidation) {
144a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // The invalidation service may send an invalidation more than once if there
145a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // is a delay in acknowledging it. Duplicate invalidations are ignored.
146a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (invalid_ && ack_handle_.Equals(invalidation.ack_handle))
147a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return;
148a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
149a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // If there is still a pending invalidation, acknowledge it, since we only
150a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // care about the latest invalidation.
151a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (invalid_)
152a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    AcknowledgeInvalidation();
153a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
154a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Update invalidation state.
155a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  invalid_ = true;
156a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ack_handle_ = invalidation.ack_handle;
157a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  invalidation_version_ = invalidation.version;
158a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
159a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // When an invalidation with unknown version is received, use negative
160a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // numbers based on the number of such invalidations received. This
161a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // ensures that the version numbers do not collide with "real" versions
162a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // (which are positive) or previous invalidations with unknown version.
163a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (invalidation_version_ == syncer::Invalidation::kUnknownVersion)
164a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    invalidation_version_ = -(++unknown_version_invalidation_count_);
165a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
166a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // In order to prevent the cloud policy server from becoming overwhelmed when
167a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // a policy with many users is modified, delay for a random period of time
168a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // before fetching the policy. Delay for at least 20ms so that if multiple
169a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // invalidations are received in quick succession, only one fetch will be
170a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // performed.
171a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  base::TimeDelta delay = base::TimeDelta::FromMilliseconds(
172a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      base::RandInt(20, max_fetch_delay_));
173a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
174a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // If there is a payload, the invalidate callback can run at any time, so set
175a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // the version and payload on the client immediately. Otherwise, the callback
176a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // must only run after at least kMissingPayloadDelay minutes.
177a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const std::string& payload = invalidation.payload;
178a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!invalidation.payload.empty())
179a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    invalidation_handler_->SetInvalidationInfo(invalidation_version_, payload);
180a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  else
181a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    delay += base::TimeDelta::FromMinutes(kMissingPayloadDelay);
182a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
183a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Schedule the invalidate callback to run.
184a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  task_runner_->PostDelayedTask(
185a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      FROM_HERE,
186a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      base::Bind(
187a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          &CloudPolicyInvalidator::RunInvalidateCallback,
188a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          weak_factory_.GetWeakPtr(),
189a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          payload.empty() /* is_missing_payload */),
190a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      delay);
191a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
192a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Update the kMetricPolicyInvalidations histogram.
193a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  UMA_HISTOGRAM_BOOLEAN(kMetricPolicyInvalidations, !payload.empty());
194a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
195a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
196a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void CloudPolicyInvalidator::UpdateRegistration(
197a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const enterprise_management::PolicyData* policy) {
198a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Create the ObjectId based on the policy data.
199a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // If the policy does not specify an the ObjectId, then unregister.
200a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!policy ||
201a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      !policy->has_timestamp() ||
202a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      !policy->has_invalidation_source() ||
203a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      !policy->has_invalidation_name()) {
204a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    Unregister();
205a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return;
206a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
207a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  invalidation::ObjectId object_id(
208a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      policy->invalidation_source(),
209a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      policy->invalidation_name());
210a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
211a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // If the policy object id in the policy data is different from the currently
212a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // registered object id, update the object registration.
213a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!registered_timestamp_ || !(object_id == object_id_))
214a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    Register(policy->timestamp(), object_id);
215a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
216a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
217a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void CloudPolicyInvalidator::Register(
218a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    int64 timestamp,
219a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const invalidation::ObjectId& object_id) {
220a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Get the invalidation service from the profile if needed.
221a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!invalidation_service_) {
222a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    DCHECK(profile_);
223a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    invalidation_service_ =
224a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        invalidation::InvalidationServiceFactory::GetForProfile(profile_);
225a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (!invalidation_service_)
226a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return;
227a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
228a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
229a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Register this handler with the invalidation service if needed.
230a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!registered_timestamp_) {
231a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    OnInvalidatorStateChange(invalidation_service_->GetInvalidatorState());
232a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    invalidation_service_->RegisterInvalidationHandler(this);
233a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
234a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
235a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Update internal state.
236a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (invalid_)
237a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    AcknowledgeInvalidation();
238a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  registered_timestamp_ = timestamp;
239a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  object_id_ = object_id;
240a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  UpdateInvalidationsEnabled();
241a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
242a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Update registration with the invalidation service.
243a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  syncer::ObjectIdSet ids;
244a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ids.insert(object_id);
245a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  invalidation_service_->UpdateRegisteredInvalidationIds(this, ids);
246a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
247a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
248a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void CloudPolicyInvalidator::Unregister() {
249a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (registered_timestamp_) {
250a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (invalid_)
251a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      AcknowledgeInvalidation();
252a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    invalidation_service_->UpdateRegisteredInvalidationIds(
253a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        this,
254a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        syncer::ObjectIdSet());
255a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    invalidation_service_->UnregisterInvalidationHandler(this);
256a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    registered_timestamp_ = 0;
257a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    UpdateInvalidationsEnabled();
258a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
259a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
260a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
261a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void CloudPolicyInvalidator::UpdateMaxFetchDelay(const PolicyMap& policy_map) {
262a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  int delay;
263a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
264a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Try reading the delay from the policy.
265a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const base::Value* delay_policy_value =
266a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      policy_map.GetValue(key::kMaxInvalidationFetchDelay);
267a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (delay_policy_value && delay_policy_value->GetAsInteger(&delay)) {
268a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    set_max_fetch_delay(delay);
269a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return;
270a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
271a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
272a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Try reading the delay from the command line switch.
273a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  std::string delay_string =
274a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
275a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          switches::kCloudPolicyInvalidationDelay);
276a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (base::StringToInt(delay_string, &delay)) {
277a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    set_max_fetch_delay(delay);
278a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return;
279a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
280a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
281a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  set_max_fetch_delay(kMaxFetchDelayDefault);
282a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
283a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
284a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void CloudPolicyInvalidator::set_max_fetch_delay(int delay) {
285a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (delay < kMaxFetchDelayMin)
286a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    max_fetch_delay_ = kMaxFetchDelayMin;
287a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  else if (delay > kMaxFetchDelayMax)
288a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    max_fetch_delay_ = kMaxFetchDelayMax;
289a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  else
290a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    max_fetch_delay_ = delay;
291a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
292a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
293a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void CloudPolicyInvalidator::UpdateInvalidationsEnabled() {
294a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  bool invalidations_enabled =
295a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      invalidation_service_enabled_ && registered_timestamp_;
296a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (invalidations_enabled_ != invalidations_enabled) {
297a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    invalidations_enabled_ = invalidations_enabled;
298a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    invalidation_handler_->OnInvalidatorStateChanged(invalidations_enabled);
299a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
300a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
301a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
302a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void CloudPolicyInvalidator::RunInvalidateCallback(bool is_missing_payload) {
303a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
304a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // In the missing payload case, the invalidation version has not been set on
305a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // the client yet, so set it now that the required time has elapsed.
306a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (is_missing_payload) {
307a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    invalidation_handler_->SetInvalidationInfo(
308a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        invalidation_version_,
309a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        std::string());
310a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
311a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  invalidation_handler_->InvalidatePolicy();
312a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
313a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
314a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void CloudPolicyInvalidator::AcknowledgeInvalidation() {
315a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(invalid_);
316a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  invalid_ = false;
317a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  invalidation_handler_->SetInvalidationInfo(0, std::string());
318a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  invalidation_service_->AcknowledgeInvalidation(object_id_, ack_handle_);
319a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Cancel any scheduled invalidate callbacks.
320a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  weak_factory_.InvalidateWeakPtrs();
321a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
322a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
323a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int CloudPolicyInvalidator::GetPolicyRefreshMetric() {
324a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (store_->policy_changed()) {
325a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (invalid_)
326a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return METRIC_POLICY_REFRESH_INVALIDATED_CHANGED;
327a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (invalidations_enabled_)
328a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return METRIC_POLICY_REFRESH_CHANGED;
329a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return METRIC_POLICY_REFRESH_CHANGED_NO_INVALIDATIONS;
330a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
331a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (invalid_)
332a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return METRIC_POLICY_REFRESH_INVALIDATED_UNCHANGED;
333a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return METRIC_POLICY_REFRESH_UNCHANGED;
334a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
335a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
336a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}  // namespace policy
337