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
3// found in the LICENSE file.
4
5#ifndef CHROME_BROWSER_POLICY_CLOUD_CLOUD_POLICY_INVALIDATOR_H_
6#define CHROME_BROWSER_POLICY_CLOUD_CLOUD_POLICY_INVALIDATOR_H_
7
8#include <string>
9
10#include "base/basictypes.h"
11#include "base/callback.h"
12#include "base/compiler_specific.h"
13#include "base/memory/ref_counted.h"
14#include "base/memory/scoped_ptr.h"
15#include "base/memory/weak_ptr.h"
16#include "base/threading/thread_checker.h"
17#include "components/invalidation/invalidation.h"
18#include "components/invalidation/invalidation_handler.h"
19#include "components/policy/core/common/cloud/cloud_policy_core.h"
20#include "components/policy/core/common/cloud/cloud_policy_store.h"
21#include "google/cacheinvalidation/include/types.h"
22#include "policy/proto/device_management_backend.pb.h"
23
24namespace base {
25class Clock;
26class SequencedTaskRunner;
27}
28
29namespace invalidation {
30class InvalidationService;
31}
32
33namespace policy {
34
35// Listens for and provides policy invalidations.
36class CloudPolicyInvalidator : public syncer::InvalidationHandler,
37                               public CloudPolicyCore::Observer,
38                               public CloudPolicyStore::Observer {
39 public:
40  // The number of minutes to delay a policy refresh after receiving an
41  // invalidation with no payload.
42  static const int kMissingPayloadDelay;
43
44  // The default, min and max values for max_fetch_delay_.
45  static const int kMaxFetchDelayDefault;
46  static const int kMaxFetchDelayMin;
47  static const int kMaxFetchDelayMax;
48
49  // The grace period, in seconds, to allow for invalidations to be received
50  // once the invalidation service starts up.
51  static const int kInvalidationGracePeriod;
52
53  // Time, in seconds, for which unknown version invalidations are ignored after
54  // fetching a policy.
55  static const int kUnknownVersionIgnorePeriod;
56
57  // The max tolerated discrepancy, in seconds, between policy timestamps and
58  // invalidation timestamps when determining if an invalidation is expired.
59  static const int kMaxInvalidationTimeDelta;
60
61  // |type| indicates the policy type that this invalidator is responsible for.
62  // |core| is the cloud policy core which connects the various policy objects.
63  // It must remain valid until Shutdown is called.
64  // |task_runner| is used for scheduling delayed tasks. It must post tasks to
65  // the main policy thread.
66  // |clock| is used to get the current time.
67  // |highest_handled_invalidation_version| is the highest invalidation version
68  // that was handled already before this invalidator was created.
69  CloudPolicyInvalidator(
70      enterprise_management::DeviceRegisterRequest::Type type,
71      CloudPolicyCore* core,
72      const scoped_refptr<base::SequencedTaskRunner>& task_runner,
73      scoped_ptr<base::Clock> clock,
74      int64 highest_handled_invalidation_version);
75  virtual ~CloudPolicyInvalidator();
76
77  // Initializes the invalidator. No invalidations will be generated before this
78  // method is called. This method must only be called once.
79  // |invalidation_service| is the invalidation service to use and must remain
80  // valid until Shutdown is called.
81  void Initialize(invalidation::InvalidationService* invalidation_service);
82
83  // Shuts down and disables invalidations. It must be called before the object
84  // is destroyed.
85  void Shutdown();
86
87  // Whether the invalidator currently has the ability to receive invalidations.
88  bool invalidations_enabled() {
89    return invalidations_enabled_;
90  }
91
92  // The highest invalidation version that was handled already.
93  int64 highest_handled_invalidation_version() const {
94    return highest_handled_invalidation_version_;
95  }
96
97  // syncer::InvalidationHandler:
98  virtual void OnInvalidatorStateChange(
99      syncer::InvalidatorState state) OVERRIDE;
100  virtual void OnIncomingInvalidation(
101      const syncer::ObjectIdInvalidationMap& invalidation_map) OVERRIDE;
102  virtual std::string GetOwnerName() const OVERRIDE;
103
104  // CloudPolicyCore::Observer:
105  virtual void OnCoreConnected(CloudPolicyCore* core) OVERRIDE;
106  virtual void OnRefreshSchedulerStarted(CloudPolicyCore* core) OVERRIDE;
107  virtual void OnCoreDisconnecting(CloudPolicyCore* core) OVERRIDE;
108
109  // CloudPolicyStore::Observer:
110  virtual void OnStoreLoaded(CloudPolicyStore* store) OVERRIDE;
111  virtual void OnStoreError(CloudPolicyStore* store) OVERRIDE;
112
113 private:
114  // Handle an invalidation to the policy.
115  void HandleInvalidation(const syncer::Invalidation& invalidation);
116
117  // Update object registration with the invalidation service based on the
118  // given policy data.
119  void UpdateRegistration(const enterprise_management::PolicyData* policy);
120
121  // Registers the given object with the invalidation service.
122  void Register(const invalidation::ObjectId& object_id);
123
124  // Unregisters the current object with the invalidation service.
125  void Unregister();
126
127  // Update |max_fetch_delay_| based on the given policy map.
128  void UpdateMaxFetchDelay(const PolicyMap& policy_map);
129  void set_max_fetch_delay(int delay);
130
131  // Updates invalidations_enabled_ and calls the invalidation handler if the
132  // value changed.
133  void UpdateInvalidationsEnabled();
134
135  // Refresh the policy.
136  // |is_missing_payload| is set to true if the callback is being invoked in
137  // response to an invalidation with a missing payload.
138  void RefreshPolicy(bool is_missing_payload);
139
140  // Acknowledge the latest invalidation.
141  void AcknowledgeInvalidation();
142
143  // Determines if the given policy is different from the policy passed in the
144  // previous call.
145  bool IsPolicyChanged(const enterprise_management::PolicyData* policy);
146
147  // Determine if an invalidation has expired.
148  // |version| is the version of the invalidation, or zero for unknown.
149  bool IsInvalidationExpired(int64 version);
150
151  // Get the kMetricPolicyRefresh histogram metric which should be incremented
152  // when a policy is stored.
153  int GetPolicyRefreshMetric(bool policy_changed);
154
155  // Get the kMetricPolicyInvalidations histogram metric which should be
156  // incremented when an invalidation is received.
157  int GetInvalidationMetric(bool is_missing_payload, bool is_expired);
158
159  // Determine if invalidations have been enabled longer than the grace period.
160  bool GetInvalidationsEnabled();
161
162  // The state of the object.
163  enum State {
164    UNINITIALIZED,
165    STOPPED,
166    STARTED,
167    SHUT_DOWN
168  };
169  State state_;
170
171  // The policy type this invalidator is responsible for.
172  const enterprise_management::DeviceRegisterRequest::Type type_;
173
174  // The cloud policy core.
175  CloudPolicyCore* core_;
176
177  // Schedules delayed tasks.
178  const scoped_refptr<base::SequencedTaskRunner> task_runner_;
179
180  // The clock.
181  scoped_ptr<base::Clock> clock_;
182
183  // The invalidation service.
184  invalidation::InvalidationService* invalidation_service_;
185
186  // Whether the invalidator currently has the ability to receive invalidations.
187  // This is true if the invalidation service is enabled and the invalidator
188  // has registered for a policy object.
189  bool invalidations_enabled_;
190
191  // The time that invalidations became enabled.
192  base::Time invalidations_enabled_time_;
193
194  // Whether the invalidation service is currently enabled.
195  bool invalidation_service_enabled_;
196
197  // Whether this object has registered for policy invalidations.
198  bool is_registered_;
199
200  // The object id representing the policy in the invalidation service.
201  invalidation::ObjectId object_id_;
202
203  // Whether the policy is current invalid. This is set to true when an
204  // invalidation is received and reset when the policy fetched due to the
205  // invalidation is stored.
206  bool invalid_;
207
208  // The version of the latest invalidation received. This is compared to
209  // the invalidation version of policy stored to determine when the
210  // invalidated policy is up-to-date.
211  int64 invalidation_version_;
212
213  // The number of invalidations with unknown version received. Since such
214  // invalidations do not provide a version number, this count is used to set
215  // invalidation_version_ when such invalidations occur.
216  int unknown_version_invalidation_count_;
217
218  // The highest invalidation version that was handled already.
219  int64 highest_handled_invalidation_version_;
220
221  // The most up to date invalidation.
222  scoped_ptr<syncer::Invalidation> invalidation_;
223
224  // The maximum random delay, in ms, between receiving an invalidation and
225  // fetching the new policy.
226  int max_fetch_delay_;
227
228  // The hash value of the current policy. This is used to determine if a new
229  // policy is different from the current one.
230  uint32 policy_hash_value_;
231
232  // A thread checker to make sure that callbacks are invoked on the correct
233  // thread.
234  base::ThreadChecker thread_checker_;
235
236  // WeakPtrFactory used to create callbacks to this object.
237  base::WeakPtrFactory<CloudPolicyInvalidator> weak_factory_;
238
239  DISALLOW_COPY_AND_ASSIGN(CloudPolicyInvalidator);
240};
241
242}  // namespace policy
243
244#endif  // CHROME_BROWSER_POLICY_CLOUD_CLOUD_POLICY_INVALIDATOR_H_
245