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_CHROMEOS_POLICY_CLOUD_EXTERNAL_DATA_POLICY_OBSERVER_H_
6#define CHROME_BROWSER_CHROMEOS_POLICY_CLOUD_EXTERNAL_DATA_POLICY_OBSERVER_H_
7
8#include <map>
9#include <string>
10
11#include "base/basictypes.h"
12#include "base/compiler_specific.h"
13#include "base/memory/linked_ptr.h"
14#include "base/memory/scoped_ptr.h"
15#include "base/memory/weak_ptr.h"
16#include "chrome/browser/chromeos/policy/device_local_account_policy_service.h"
17#include "chrome/browser/chromeos/settings/cros_settings.h"
18#include "components/policy/core/common/policy_map.h"
19#include "content/public/browser/notification_observer.h"
20#include "content/public/browser/notification_registrar.h"
21
22namespace policy {
23
24// Helper for implementing policies referencing external data: This class
25// observes a given |policy_| and fetches the external data that it references
26// for all users on the device. Notifications are emitted when an external data
27// reference is set, cleared or an external data fetch completes successfully.
28//
29// State is kept at runtime only: External data references that already exist
30// when the class is instantiated are considered new, causing a notification to
31// be emitted that an external data reference has been set and the referenced
32// external data to be fetched.
33class CloudExternalDataPolicyObserver
34    : public content::NotificationObserver,
35      public DeviceLocalAccountPolicyService::Observer {
36 public:
37  class Delegate {
38   public:
39    // Invoked when an external data reference is set for |user_id|.
40    virtual void OnExternalDataSet(const std::string& policy,
41                                   const std::string& user_id);
42
43    // Invoked when the external data reference is cleared for |user_id|.
44    virtual void OnExternalDataCleared(const std::string& policy,
45                                       const std::string& user_id);
46
47    // Invoked when the external data referenced for |user_id| has been fetched.
48    // Failed fetches are retried and the method is called only when a fetch
49    // eventually succeeds. If a fetch fails permanently (e.g. because the
50    // external data reference specifies an invalid URL), the method is not
51    // called at all.
52    virtual void OnExternalDataFetched(const std::string& policy,
53                                       const std::string& user_id,
54                                       scoped_ptr<std::string> data);
55
56   protected:
57    virtual ~Delegate();
58  };
59
60  CloudExternalDataPolicyObserver(
61      chromeos::CrosSettings* cros_settings,
62      DeviceLocalAccountPolicyService* device_local_account_policy_service,
63      const std::string& policy,
64      Delegate* delegate);
65  virtual ~CloudExternalDataPolicyObserver();
66
67  void Init();
68
69  // content::NotificationObserver:
70  virtual void Observe(int type,
71                       const content::NotificationSource& source,
72                       const content::NotificationDetails& details) OVERRIDE;
73
74  // DeviceLocalAccountPolicyService::Observer:
75  virtual void OnPolicyUpdated(const std::string& user_id) OVERRIDE;
76  virtual void OnDeviceLocalAccountsChanged() OVERRIDE;
77
78 private:
79  // Helper class that observes |policy_| for a logged-in user.
80  class PolicyServiceObserver;
81
82  void RetrieveDeviceLocalAccounts();
83
84  // Handles the new policy map |entry| for |user_id| by canceling any external
85  // data fetch currently in progress, emitting a notification that an external
86  // data reference has been cleared (if |entry| is NULL) or set (otherwise),
87  // starting a new external data fetch in the latter case.
88  void HandleExternalDataPolicyUpdate(const std::string& user_id,
89                                      const PolicyMap::Entry* entry);
90
91  void OnExternalDataFetched(const std::string& user_id,
92                             scoped_ptr<std::string> data);
93
94  // A map from each device-local account user ID to its current policy map
95  // entry for |policy_|.
96  typedef std::map<std::string, PolicyMap::Entry> DeviceLocalAccountEntryMap;
97  DeviceLocalAccountEntryMap device_local_account_entries_;
98
99  // A map from each logged-in user to the helper that observes |policy_| in the
100  // user's PolicyService.
101  typedef std::map<std::string, linked_ptr<PolicyServiceObserver> >
102      LoggedInUserObserverMap;
103  LoggedInUserObserverMap logged_in_user_observers_;
104
105  chromeos::CrosSettings* cros_settings_;
106  DeviceLocalAccountPolicyService* device_local_account_policy_service_;
107
108  // The policy that |this| observes.
109  std::string policy_;
110
111  Delegate* delegate_;
112
113  content::NotificationRegistrar notification_registrar_;
114  scoped_ptr<chromeos::CrosSettings::ObserverSubscription>
115      device_local_accounts_subscription_;
116
117  // A map from user ID to a base::WeakPtr for each external data fetch
118  // currently in progress. This allows fetches to be effectively be canceled by
119  // invalidating the pointers.
120  typedef base::WeakPtrFactory<CloudExternalDataPolicyObserver>
121      WeakPtrFactory;
122  typedef std::map<std::string, linked_ptr<WeakPtrFactory> > FetchWeakPtrMap;
123  FetchWeakPtrMap fetch_weak_ptrs_;
124
125  base::WeakPtrFactory<CloudExternalDataPolicyObserver> weak_factory_;
126
127  DISALLOW_COPY_AND_ASSIGN(CloudExternalDataPolicyObserver);
128};
129
130}  // namespace policy
131
132#endif  // CHROME_BROWSER_CHROMEOS_POLICY_CLOUD_EXTERNAL_DATA_POLICY_OBSERVER_H_
133