Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / prefs / pref_hash_filter.cc
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 #include "chrome/browser/prefs/pref_hash_filter.h"
6
7 #include <algorithm>
8
9 #include "base/logging.h"
10 #include "base/metrics/histogram.h"
11 #include "base/prefs/pref_store.h"
12 #include "base/time/time.h"
13 #include "base/values.h"
14 #include "chrome/browser/prefs/pref_hash_store_transaction.h"
15 #include "chrome/browser/prefs/tracked/tracked_atomic_preference.h"
16 #include "chrome/browser/prefs/tracked/tracked_split_preference.h"
17
18 PrefHashFilter::PrefHashFilter(
19     scoped_ptr<PrefHashStore> pref_hash_store,
20     const TrackedPreferenceMetadata tracked_preferences[],
21     size_t tracked_preferences_size,
22     size_t reporting_ids_count,
23     EnforcementLevel enforcement_level,
24     const base::Closure& reset_callback)
25         : pref_hash_store_(pref_hash_store.Pass()),
26           reset_callback_(reset_callback) {
27   DCHECK(pref_hash_store_);
28   DCHECK_GE(reporting_ids_count, tracked_preferences_size);
29
30   for (size_t i = 0; i < tracked_preferences_size; ++i) {
31     const TrackedPreferenceMetadata& metadata = tracked_preferences[i];
32
33     EnforcementLevel enforcement_level_for_pref =
34         std::min(enforcement_level, metadata.max_enforcement_level);
35
36     scoped_ptr<TrackedPreference> tracked_preference;
37     switch (metadata.strategy) {
38       case TRACKING_STRATEGY_ATOMIC:
39         tracked_preference.reset(
40             new TrackedAtomicPreference(metadata.name, metadata.reporting_id,
41                                         reporting_ids_count,
42                                         enforcement_level_for_pref));
43         break;
44       case TRACKING_STRATEGY_SPLIT:
45         tracked_preference.reset(
46             new TrackedSplitPreference(metadata.name, metadata.reporting_id,
47                                        reporting_ids_count,
48                                        enforcement_level_for_pref));
49         break;
50     }
51     DCHECK(tracked_preference);
52
53     bool is_new = tracked_paths_.add(metadata.name,
54                                      tracked_preference.Pass()).second;
55     DCHECK(is_new);
56   }
57 }
58
59 PrefHashFilter::~PrefHashFilter() {
60   // Ensure new values for all |changed_paths_| have been flushed to
61   // |pref_hash_store_| already.
62   DCHECK(changed_paths_.empty());
63 }
64
65 void PrefHashFilter::Initialize(const PrefStore& pref_store) {
66   scoped_ptr<PrefHashStoreTransaction> hash_store_transaction(
67       pref_hash_store_->BeginTransaction());
68   for (TrackedPreferencesMap::const_iterator it = tracked_paths_.begin();
69        it != tracked_paths_.end(); ++it) {
70     const std::string& initialized_path = it->first;
71     const TrackedPreference* initialized_preference = it->second;
72     const base::Value* value = NULL;
73     pref_store.GetValue(initialized_path, &value);
74     initialized_preference->OnNewValue(value, hash_store_transaction.get());
75   }
76 }
77
78 // Validates loaded preference values according to stored hashes, reports
79 // validation results via UMA, and updates hashes in case of mismatch.
80 void PrefHashFilter::FilterOnLoad(base::DictionaryValue* pref_store_contents) {
81   DCHECK(pref_store_contents);
82   base::TimeTicks checkpoint = base::TimeTicks::Now();
83
84   bool did_reset = false;
85   {
86     scoped_ptr<PrefHashStoreTransaction> hash_store_transaction(
87         pref_hash_store_->BeginTransaction());
88     for (TrackedPreferencesMap::const_iterator it = tracked_paths_.begin();
89          it != tracked_paths_.end(); ++it) {
90       if (it->second->EnforceAndReport(pref_store_contents,
91                                        hash_store_transaction.get())) {
92         did_reset = true;
93       }
94     }
95   }
96
97   if (did_reset)
98     reset_callback_.Run();
99
100   // TODO(gab): Remove this histogram by Feb 21 2014; after sufficient timing
101   // data has been gathered from the wild to be confident this doesn't
102   // significantly affect startup.
103   UMA_HISTOGRAM_TIMES("Settings.FilterOnLoadTime",
104                       base::TimeTicks::Now() - checkpoint);
105 }
106
107 // Marks |path| has having changed if it is part of |tracked_paths_|. A new hash
108 // will be stored for it the next time FilterSerializeData() is invoked.
109 void PrefHashFilter::FilterUpdate(const std::string& path) {
110   TrackedPreferencesMap::const_iterator it = tracked_paths_.find(path);
111   if (it != tracked_paths_.end())
112     changed_paths_.insert(std::make_pair(path, it->second));
113 }
114
115 // Updates the stored hashes for |changed_paths_| before serializing data to
116 // disk. This is required as storing the hash everytime a pref's value changes
117 // is too expensive (see perf regression @ http://crbug.com/331273).
118 void PrefHashFilter::FilterSerializeData(
119     const base::DictionaryValue* pref_store_contents) {
120   if (!changed_paths_.empty()) {
121     base::TimeTicks checkpoint = base::TimeTicks::Now();
122     {
123       scoped_ptr<PrefHashStoreTransaction> hash_store_transaction(
124           pref_hash_store_->BeginTransaction());
125       for (ChangedPathsMap::const_iterator it = changed_paths_.begin();
126            it != changed_paths_.end(); ++it) {
127         const std::string& changed_path = it->first;
128         const TrackedPreference* changed_preference = it->second;
129         const base::Value* value = NULL;
130         pref_store_contents->Get(changed_path, &value);
131         changed_preference->OnNewValue(value, hash_store_transaction.get());
132       }
133       changed_paths_.clear();
134     }
135     // TODO(gab): Remove this histogram by Feb 21 2014; after sufficient timing
136     // data has been gathered from the wild to be confident this doesn't
137     // significantly affect performance on the UI thread.
138     UMA_HISTOGRAM_TIMES("Settings.FilterSerializeDataTime",
139                         base::TimeTicks::Now() - checkpoint);
140   }
141 }