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 COMPONENTS_POLICY_CORE_COMMON_ASYNC_POLICY_LOADER_H_
6#define COMPONENTS_POLICY_CORE_COMMON_ASYNC_POLICY_LOADER_H_
7
8#include "base/callback.h"
9#include "base/memory/ref_counted.h"
10#include "base/memory/scoped_ptr.h"
11#include "base/memory/weak_ptr.h"
12#include "base/time/time.h"
13#include "components/policy/core/common/schema_map.h"
14#include "components/policy/policy_export.h"
15
16namespace base {
17class SequencedTaskRunner;
18}
19
20namespace policy {
21
22class PolicyBundle;
23
24// Base implementation for platform-specific policy loaders. Together with the
25// AsyncPolicyProvider, this base implementation takes care of the initial load,
26// periodic reloads, watching file changes, refreshing policies and object
27// lifetime.
28//
29// All methods are invoked on the background |task_runner_|, including the
30// destructor. The only exceptions are the constructor (which may be called on
31// any thread), and the initial Load() which is called on the thread that owns
32// the provider.
33// LastModificationTime() is also invoked once on that thread at startup.
34class POLICY_EXPORT AsyncPolicyLoader {
35 public:
36  explicit AsyncPolicyLoader(
37      scoped_refptr<base::SequencedTaskRunner> task_runner);
38  virtual ~AsyncPolicyLoader();
39
40  // Gets a SequencedTaskRunner backed by the background thread.
41  base::SequencedTaskRunner* task_runner() const { return task_runner_.get(); }
42
43  // Returns the currently configured policies. Load() is always invoked on
44  // the background thread, except for the initial Load() at startup which is
45  // invoked from the thread that owns the provider.
46  virtual scoped_ptr<PolicyBundle> Load() = 0;
47
48  // Allows implementations to finalize their initialization on the background
49  // thread (e.g. setup file watchers).
50  virtual void InitOnBackgroundThread() = 0;
51
52  // Implementations should return the time of the last modification detected,
53  // or base::Time() if it doesn't apply, which is the default.
54  virtual base::Time LastModificationTime();
55
56  // Used by the AsyncPolicyProvider to do the initial Load(). The first load
57  // is also used to initialize |last_modification_time_| and
58  // |schema_map_|.
59  scoped_ptr<PolicyBundle> InitialLoad(const scoped_refptr<SchemaMap>& schemas);
60
61  // Implementations should invoke Reload() when a change is detected. This
62  // must be invoked from the background thread and will trigger a Load(),
63  // and pass the returned bundle to the provider.
64  // The load is immediate when |force| is true. Otherwise, the loader
65  // reschedules the reload until the LastModificationTime() is a couple of
66  // seconds in the past. This mitigates the problem of reading files that are
67  // currently being written to, and whose contents are incomplete.
68  // A reload is posted periodically, if it hasn't been triggered recently. This
69  // makes sure the policies are reloaded if the update events aren't triggered.
70  void Reload(bool force);
71
72  const scoped_refptr<SchemaMap>& schema_map() const { return schema_map_; }
73
74 private:
75  // Allow AsyncPolicyProvider to call Init().
76  friend class AsyncPolicyProvider;
77
78  typedef base::Callback<void(scoped_ptr<PolicyBundle>)> UpdateCallback;
79
80  // Used by the AsyncPolicyProvider to install the |update_callback_|.
81  // Invoked on the background thread.
82  void Init(const UpdateCallback& update_callback);
83
84  // Used by the AsyncPolicyProvider to reload with an updated SchemaMap.
85  void RefreshPolicies(scoped_refptr<SchemaMap> schema_map);
86
87  // Cancels any pending periodic reload and posts one |delay| time units from
88  // now.
89  void ScheduleNextReload(base::TimeDelta delay);
90
91  // Checks if the underlying files haven't changed recently, by checking the
92  // LastModificationTime(). |delay| is updated with a suggested time to wait
93  // before retrying when this returns false.
94  bool IsSafeToReload(const base::Time& now, base::TimeDelta* delay);
95
96  // Task runner to run background threads.
97  scoped_refptr<base::SequencedTaskRunner> task_runner_;
98
99  // Callback for updates, passed in Init().
100  UpdateCallback update_callback_;
101
102  // Records last known modification timestamp.
103  base::Time last_modification_time_;
104
105  // The wall clock time at which the last modification timestamp was
106  // recorded.  It's better to not assume the file notification time and the
107  // wall clock times come from the same source, just in case there is some
108  // non-local filesystem involved.
109  base::Time last_modification_clock_;
110
111  // The current policy schemas that this provider should load.
112  scoped_refptr<SchemaMap> schema_map_;
113
114  // Used to get WeakPtrs for the periodic reload task.
115  base::WeakPtrFactory<AsyncPolicyLoader> weak_factory_;
116
117  DISALLOW_COPY_AND_ASSIGN(AsyncPolicyLoader);
118};
119
120}  // namespace policy
121
122#endif  // COMPONENTS_POLICY_CORE_COMMON_ASYNC_POLICY_LOADER_H_
123