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_PREFS_PREF_HASH_FILTER_H_
6#define CHROME_BROWSER_PREFS_PREF_HASH_FILTER_H_
7
8#include <map>
9#include <set>
10#include <vector>
11
12#include "base/basictypes.h"
13#include "base/callback.h"
14#include "base/compiler_specific.h"
15#include "base/containers/scoped_ptr_hash_map.h"
16#include "base/memory/scoped_ptr.h"
17#include "chrome/browser/prefs/interceptable_pref_filter.h"
18#include "chrome/browser/prefs/tracked/tracked_preference.h"
19
20class PrefHashStore;
21class PrefService;
22class PrefStore;
23class TrackedPreferenceValidationDelegate;
24
25namespace base {
26class DictionaryValue;
27class Time;
28class Value;
29}  // namespace base
30
31namespace user_prefs {
32class PrefRegistrySyncable;
33}  // namespace user_prefs
34
35// Intercepts preference values as they are loaded from disk and verifies them
36// using a PrefHashStore. Keeps the PrefHashStore contents up to date as values
37// are changed.
38class PrefHashFilter : public InterceptablePrefFilter {
39 public:
40  enum EnforcementLevel {
41    NO_ENFORCEMENT,
42    ENFORCE_ON_LOAD
43  };
44
45  enum PrefTrackingStrategy {
46    // Atomic preferences are tracked as a whole.
47    TRACKING_STRATEGY_ATOMIC,
48    // Split preferences are dictionaries for which each top-level entry is
49    // tracked independently. Note: preferences using this strategy must be kept
50    // in sync with TrackedSplitPreferences in histograms.xml.
51    TRACKING_STRATEGY_SPLIT,
52  };
53
54  struct TrackedPreferenceMetadata {
55    size_t reporting_id;
56    const char* name;
57    EnforcementLevel enforcement_level;
58    PrefTrackingStrategy strategy;
59  };
60
61  // Constructs a PrefHashFilter tracking the specified |tracked_preferences|
62  // using |pref_hash_store| to check/store hashes. An optional |delegate| is
63  // notified of the status of each preference as it is checked.
64  // If |on_reset_on_load| is provided, it will be invoked if a reset occurs in
65  // FilterOnLoad.
66  // |reporting_ids_count| is the count of all possible IDs (possibly greater
67  // than |tracked_preferences.size()|). If |report_super_mac_validity| is true,
68  // the state of the super MAC will be reported via UMA during
69  // FinalizeFilterOnLoad.
70  PrefHashFilter(
71      scoped_ptr<PrefHashStore> pref_hash_store,
72      const std::vector<TrackedPreferenceMetadata>& tracked_preferences,
73      const base::Closure& on_reset_on_load,
74      TrackedPreferenceValidationDelegate* delegate,
75      size_t reporting_ids_count,
76      bool report_super_mac_validity);
77
78  virtual ~PrefHashFilter();
79
80  // Registers required user preferences.
81  static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
82
83  // Retrieves the time of the last reset event, if any, for the provided user
84  // preferences. If no reset has occurred, Returns a null |Time|.
85  static base::Time GetResetTime(PrefService* user_prefs);
86
87  // Clears the time of the last reset event, if any, for the provided user
88  // preferences.
89  static void ClearResetTime(PrefService* user_prefs);
90
91  // Initializes the PrefHashStore with hashes of the tracked preferences in
92  // |pref_store_contents|. |pref_store_contents| will be the |storage| passed
93  // to PrefHashStore::BeginTransaction().
94  void Initialize(base::DictionaryValue* pref_store_contents);
95
96  // PrefFilter remaining implementation.
97  virtual void FilterUpdate(const std::string& path) OVERRIDE;
98  virtual void FilterSerializeData(
99      base::DictionaryValue* pref_store_contents) OVERRIDE;
100
101 private:
102  // InterceptablePrefFilter implementation.
103  virtual void FinalizeFilterOnLoad(
104      const PostFilterOnLoadCallback& post_filter_on_load_callback,
105      scoped_ptr<base::DictionaryValue> pref_store_contents,
106      bool prefs_altered) OVERRIDE;
107
108  // Callback to be invoked only once (and subsequently reset) on the next
109  // FilterOnLoad event. It will be allowed to modify the |prefs| handed to
110  // FilterOnLoad before handing them back to this PrefHashFilter.
111  FilterOnLoadInterceptor filter_on_load_interceptor_;
112
113  // A map of paths to TrackedPreferences; this map owns this individual
114  // TrackedPreference objects.
115  typedef base::ScopedPtrHashMap<std::string, TrackedPreference>
116      TrackedPreferencesMap;
117  // A map from changed paths to their corresponding TrackedPreferences (which
118  // aren't owned by this map).
119  typedef std::map<std::string, const TrackedPreference*> ChangedPathsMap;
120
121  scoped_ptr<PrefHashStore> pref_hash_store_;
122
123  // Invoked if a reset occurs in a call to FilterOnLoad.
124  const base::Closure on_reset_on_load_;
125
126  TrackedPreferencesMap tracked_paths_;
127
128  // The set of all paths whose value has changed since the last call to
129  // FilterSerializeData.
130  ChangedPathsMap changed_paths_;
131
132  // Whether to report the validity of the super MAC at load time (via UMA).
133  bool report_super_mac_validity_;
134
135  DISALLOW_COPY_AND_ASSIGN(PrefHashFilter);
136};
137
138#endif  // CHROME_BROWSER_PREFS_PREF_HASH_FILTER_H_
139