| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CHROME_BROWSER_POLICY_ASYNC_POLICY_LOADER_H_ |
| #define CHROME_BROWSER_POLICY_ASYNC_POLICY_LOADER_H_ |
| |
| #include <map> |
| |
| #include "base/callback.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/time/time.h" |
| #include "chrome/browser/policy/policy_service.h" |
| |
| namespace base { |
| class SequencedTaskRunner; |
| } |
| |
| namespace policy { |
| |
| class PolicyBundle; |
| class PolicyDomainDescriptor; |
| |
| // Base implementation for platform-specific policy loaders. Together with the |
| // AsyncPolicyProvider, this base implementation takes care of the initial load, |
| // periodic reloads, watching file changes, refreshing policies and object |
| // lifetime. |
| // |
| // All methods are invoked on the background |task_runner_|, including the |
| // destructor. The only exceptions are the constructor (which may be called on |
| // any thread), and the initial Load() which is called on the thread that owns |
| // the provider. |
| // LastModificationTime() is also invoked once on that thread at startup. |
| class AsyncPolicyLoader { |
| public: |
| explicit AsyncPolicyLoader( |
| scoped_refptr<base::SequencedTaskRunner> task_runner); |
| virtual ~AsyncPolicyLoader(); |
| |
| // Gets a SequencedTaskRunner backed by the background thread. |
| base::SequencedTaskRunner* task_runner() const { return task_runner_.get(); } |
| |
| // Returns the currently configured policies. Load() is always invoked on |
| // the background thread, except for the initial Load() at startup which is |
| // invoked from the thread that owns the provider. |
| virtual scoped_ptr<PolicyBundle> Load() = 0; |
| |
| // Allows implementations to finalize their initialization on the background |
| // thread (e.g. setup file watchers). |
| virtual void InitOnBackgroundThread() = 0; |
| |
| // Implementations should return the time of the last modification detected, |
| // or base::Time() if it doesn't apply, which is the default. |
| virtual base::Time LastModificationTime(); |
| |
| // Implementations should invoke Reload() when a change is detected. This |
| // must be invoked from the background thread and will trigger a Load(), |
| // and pass the returned bundle to the provider. |
| // The load is immediate when |force| is true. Otherwise, the loader |
| // reschedules the reload until the LastModificationTime() is a couple of |
| // seconds in the past. This mitigates the problem of reading files that are |
| // currently being written to, and whose contents are incomplete. |
| // A reload is posted periodically, if it hasn't been triggered recently. This |
| // makes sure the policies are reloaded if the update events aren't triggered. |
| void Reload(bool force); |
| |
| // Passes the current |descriptor| for a domain, which is used to determine |
| // which policy names are supported for each component. |
| void RegisterPolicyDomain( |
| scoped_refptr<const PolicyDomainDescriptor> descriptor); |
| |
| protected: |
| typedef std::map<PolicyDomain, scoped_refptr<const PolicyDomainDescriptor> > |
| DescriptorMap; |
| |
| // Returns the current DescriptorMap. This can be used by implementations to |
| // determine the components registered for each domain, and to filter out |
| // unknonwn policies. |
| const DescriptorMap& descriptor_map() const { return descriptor_map_; } |
| |
| private: |
| // Allow AsyncPolicyProvider to call Init(). |
| friend class AsyncPolicyProvider; |
| |
| typedef base::Callback<void(scoped_ptr<PolicyBundle>)> UpdateCallback; |
| |
| // Used by the AsyncPolicyProvider to do the initial Load(). The first load |
| // is also used to initialize |last_modification_time_|. |
| scoped_ptr<PolicyBundle> InitialLoad(); |
| |
| // Used by the AsyncPolicyProvider to install the |update_callback_|. |
| // Invoked on the background thread. |
| void Init(const UpdateCallback& update_callback); |
| |
| // Cancels any pending periodic reload and posts one |delay| time units from |
| // now. |
| void ScheduleNextReload(base::TimeDelta delay); |
| |
| // Checks if the underlying files haven't changed recently, by checking the |
| // LastModificationTime(). |delay| is updated with a suggested time to wait |
| // before retrying when this returns false. |
| bool IsSafeToReload(const base::Time& now, base::TimeDelta* delay); |
| |
| // Task runner to run background threads. |
| scoped_refptr<base::SequencedTaskRunner> task_runner_; |
| |
| // Callback for updates, passed in Init(). |
| UpdateCallback update_callback_; |
| |
| // Used to get WeakPtrs for the periodic reload task. |
| base::WeakPtrFactory<AsyncPolicyLoader> weak_factory_; |
| |
| // Records last known modification timestamp. |
| base::Time last_modification_time_; |
| |
| // The wall clock time at which the last modification timestamp was |
| // recorded. It's better to not assume the file notification time and the |
| // wall clock times come from the same source, just in case there is some |
| // non-local filesystem involved. |
| base::Time last_modification_clock_; |
| |
| // A map of the currently registered domains and their descriptors. |
| DescriptorMap descriptor_map_; |
| |
| DISALLOW_COPY_AND_ASSIGN(AsyncPolicyLoader); |
| }; |
| |
| } // namespace policy |
| |
| #endif // CHROME_BROWSER_POLICY_ASYNC_POLICY_LOADER_H_ |