1// Copyright (c) 2012 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_POLICY_SERVICE_H_
6#define CHROME_BROWSER_POLICY_POLICY_SERVICE_H_
7
8#include <map>
9#include <string>
10
11#include "base/basictypes.h"
12#include "base/callback.h"
13#include "base/memory/ref_counted.h"
14#include "chrome/browser/policy/policy_map.h"
15
16namespace policy {
17
18class PolicyDomainDescriptor;
19
20// Policies are namespaced by a (PolicyDomain, ID) pair. The meaning of the ID
21// string depends on the domain; for example, if the PolicyDomain is
22// "extensions" then the ID identifies the extension that the policies control.
23enum PolicyDomain {
24  // The component ID for chrome policies is always the empty string.
25  POLICY_DOMAIN_CHROME,
26
27  // The extensions policy domain is a work in progress. Included here for
28  // tests.
29  POLICY_DOMAIN_EXTENSIONS,
30
31  // Must be the last entry.
32  POLICY_DOMAIN_SIZE,
33};
34
35// Groups a policy domain and a component ID in a single object representing
36// a policy namespace. Objects of this class can be used as keys in std::maps.
37struct PolicyNamespace {
38 public:
39  PolicyNamespace();
40  PolicyNamespace(PolicyDomain domain, const std::string& component_id);
41  PolicyNamespace(const PolicyNamespace& other);
42  ~PolicyNamespace();
43
44  PolicyNamespace& operator=(const PolicyNamespace& other);
45  bool operator<(const PolicyNamespace& other) const;
46  bool operator==(const PolicyNamespace& other) const;
47  bool operator!=(const PolicyNamespace& other) const;
48
49  PolicyDomain domain;
50  std::string component_id;
51};
52
53// The PolicyService merges policies from all available sources, taking into
54// account their priorities. Policy clients can retrieve policy for their domain
55// and register for notifications on policy updates.
56//
57// The PolicyService is available from BrowserProcess as a global singleton.
58// There is also a PolicyService for browser-wide policies available from
59// BrowserProcess as a global singleton.
60class PolicyService {
61 public:
62  class Observer {
63   public:
64    // Invoked whenever policies for the given |ns| namespace are modified.
65    // This is only invoked for changes that happen after AddObserver is called.
66    // |previous| contains the values of the policies before the update,
67    // and |current| contains the current values.
68    virtual void OnPolicyUpdated(const PolicyNamespace& ns,
69                                 const PolicyMap& previous,
70                                 const PolicyMap& current) = 0;
71
72    // Invoked at most once for each |domain|, when the PolicyService becomes
73    // ready. If IsInitializationComplete() is false, then this will be invoked
74    // once all the policy providers have finished loading their policies for
75    // |domain|.
76    virtual void OnPolicyServiceInitialized(PolicyDomain domain) {}
77
78   protected:
79    virtual ~Observer() {}
80  };
81
82  virtual ~PolicyService() {}
83
84  // Observes changes to all components of the given |domain|.
85  virtual void AddObserver(PolicyDomain domain, Observer* observer) = 0;
86
87  virtual void RemoveObserver(PolicyDomain domain, Observer* observer) = 0;
88
89  // Registers the |descriptor| of a policy domain, indicated by
90  // |descriptor->domain()|. This overrides the descriptor previously set, if
91  // there was one.
92  // This registration signals that there is interest in receiving policy for
93  // the components listed in the descriptor. The policy providers will try to
94  // load policy for these components, and validate it against the descriptor.
95  // Cached data for components that aren't registered anymore may be dropped.
96  virtual void RegisterPolicyDomain(
97      scoped_refptr<const PolicyDomainDescriptor> descriptor) = 0;
98
99  virtual const PolicyMap& GetPolicies(const PolicyNamespace& ns) const = 0;
100
101  virtual scoped_refptr<const PolicyDomainDescriptor> GetPolicyDomainDescriptor(
102      PolicyDomain domain) const = 0;
103
104  // The PolicyService loads policy from several sources, and some require
105  // asynchronous loads. IsInitializationComplete() returns true once all
106  // sources have loaded their policies for the given |domain|.
107  // It is safe to read policy from the PolicyService even if
108  // IsInitializationComplete() is false; there will be an OnPolicyUpdated()
109  // notification once new policies become available.
110  //
111  // OnPolicyServiceInitialized() is called when IsInitializationComplete()
112  // becomes true, which happens at most once for each domain.
113  // If IsInitializationComplete() is already true for |domain| when an Observer
114  // is registered, then that Observer will not receive an
115  // OnPolicyServiceInitialized() notification.
116  virtual bool IsInitializationComplete(PolicyDomain domain) const = 0;
117
118  // Asks the PolicyService to reload policy from all available policy sources.
119  // |callback| is invoked once every source has reloaded its policies, and
120  // GetPolicies() is guaranteed to return the updated values at that point.
121  virtual void RefreshPolicies(const base::Closure& callback) = 0;
122};
123
124// A registrar that only observes changes to particular policies within the
125// PolicyMap for the given policy namespace.
126class PolicyChangeRegistrar : public PolicyService::Observer {
127 public:
128  typedef base::Callback<void(const Value*, const Value*)> UpdateCallback;
129
130  // Observes updates to the given (domain, component_id) namespace in the given
131  // |policy_service|, and notifies |observer| whenever any of the registered
132  // policy keys changes. Both the |policy_service| and the |observer| must
133  // outlive |this|.
134  PolicyChangeRegistrar(PolicyService* policy_service,
135                        const PolicyNamespace& ns);
136
137  virtual ~PolicyChangeRegistrar();
138
139  // Will invoke |callback| whenever |policy_name| changes its value, as long
140  // as this registrar exists.
141  // Only one callback can be registed per policy name; a second call with the
142  // same |policy_name| will overwrite the previous callback.
143  void Observe(const std::string& policy_name, const UpdateCallback& callback);
144
145  // Implementation of PolicyService::Observer:
146  virtual void OnPolicyUpdated(const PolicyNamespace& ns,
147                               const PolicyMap& previous,
148                               const PolicyMap& current) OVERRIDE;
149
150 private:
151  typedef std::map<std::string, UpdateCallback> CallbackMap;
152
153  PolicyService* policy_service_;
154  PolicyNamespace ns_;
155  CallbackMap callback_map_;
156
157  DISALLOW_COPY_AND_ASSIGN(PolicyChangeRegistrar);
158};
159
160}  // namespace policy
161
162#endif  // CHROME_BROWSER_POLICY_POLICY_SERVICE_H_
163