Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(198)

Side by Side Diff: chrome/browser/prefs/pref_hash_store_impl.cc

Issue 90563003: Fix a race condition in preference metric reporting. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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_store_impl.h"
6
7 #include "base/logging.h"
8 #include "base/prefs/pref_service.h"
9 #include "base/prefs/scoped_user_pref_update.h"
10 #include "base/values.h"
11 #include "chrome/browser/prefs/pref_hash_tracker.h"
12 #include "chrome/common/pref_names.h"
13
14 // Implements PrefHashTracker by storing hashes in a PrefService.
15 class PrefHashStoreImpl::PrefHashTrackerImpl : public PrefHashTracker {
16 public:
17 // Constructs a PrefHashTrackerImpl that calculates hashes of preference
18 // values using |pref_hash_calculator| and stores them in |local_state|.
19 // Multiple hash trackers can use the same |local_state| with distinct
20 // |hash_store_id|s.
21 //
22 // Values are stored at kProfilePreferenceHashes / |hash_store_id| / path,
robertshield 2013/11/28 02:54:26 nit: should this be prefs::kProfilePreferenceHashe
23 // where path is the full path of the tracked preference.
24 // |hash_store_id| is not expanded but path and kProfilePreferenceHashes
robertshield 2013/11/28 02:54:26 please elaborate slightly on what "expanded" means
25 // are.
26 PrefHashTrackerImpl(PrefService* local_state,
27 const std::string& hash_store_id,
28 const PrefHashCalculator& pref_hash_calculator);
29
30 // Adds |path| to the set of preferences for which hashes will be stored.
31 void Track(const std::string& path);
32
33 // Updates the stored hash for |path|, if |path| has been configured for
gab 2013/11/27 23:43:27 I think this sentence flows better without the com
34 // tracking by calling |Track|. |new_value| may be NULL if there is no value
35 // |path|.
gab 2013/11/27 23:43:27 "no value *at* |path|?"
36 virtual void OnPrefValueChanged(const std::string& path,
37 const base::Value* new_value) OVERRIDE;
38
39 private:
40 std::set<std::string> tracked_paths_;
41 PrefService* local_state_;
42 std::string hash_store_id_;
43 PrefHashCalculator pref_hash_calculator_;
44
45 DISALLOW_COPY_AND_ASSIGN(PrefHashTrackerImpl);
46 };
47
48 PrefHashStoreImpl::PrefHashTrackerImpl::PrefHashTrackerImpl(
49 PrefService* local_state,
50 const std::string& hash_store_id,
51 const PrefHashCalculator& pref_hash_calculator)
52 : local_state_(local_state),
53 hash_store_id_(hash_store_id),
54 pref_hash_calculator_(pref_hash_calculator) {}
55
56 void PrefHashStoreImpl::PrefHashTrackerImpl::Track(const std::string& path) {
57 tracked_paths_.insert(path);
gab 2013/11/27 23:43:27 Why not use the PrefChangeRegistrar for this? Is i
erikwright (departed) 2013/11/28 17:48:07 We're dealing with a PrefStore, not a PrefService.
58 }
59
60 void PrefHashStoreImpl::PrefHashTrackerImpl::OnPrefValueChanged(
61 const std::string& path, const base::Value* new_value) {
62 if (tracked_paths_.find(path) == tracked_paths_.end())
63 return;
64
65 DictionaryPrefUpdate update(local_state_, prefs::kProfilePreferenceHashes);
66 DictionaryValue* child_dictionary = NULL;
67
68 // Get the dictionary corresponding to the profile name,
gab 2013/11/27 23:43:27 s/profile name/hash store id
69 // which may have a '.'
70 if (!update->GetDictionaryWithoutPathExpansion(hash_store_id_,
71 &child_dictionary)) {
72 child_dictionary = new DictionaryValue;
73 update->SetWithoutPathExpansion(hash_store_id_, child_dictionary);
74 }
75
76 child_dictionary->SetString(
77 path, pref_hash_calculator_.Calculate(path, new_value));
78 }
79
80 PrefHashStoreImpl::PrefHashStoreImpl(const std::string& seed,
81 PrefService* local_state,
82 const std::string& hash_store_id)
83 : local_state_(local_state),
84 hash_store_id_(hash_store_id),
85 pref_hash_calculator_(seed),
86 pref_hash_tracker_(new PrefHashTrackerImpl(
87 local_state_, hash_store_id, pref_hash_calculator_)) {}
88
89 PrefHashStore::InitializationResult PrefHashStoreImpl::InitializeTrackedValue(
90 const std::string& path, const base::Value* initial_value) {
91 DCHECK(pref_hash_tracker_.get());
92 if (!pref_hash_tracker_.get())
gab 2013/11/27 23:43:27 Why handle this case with silent success? The cont
93 return PrefHashStore::UNCHANGED;
94
95 pref_hash_tracker_->Track(path);
96
97 const base::DictionaryValue* pref_hash_dicts =
98 local_state_->GetDictionary(prefs::kProfilePreferenceHashes);
99 const base::DictionaryValue* hashed_prefs = NULL;
100 pref_hash_dicts->GetDictionaryWithoutPathExpansion(hash_store_id_,
101 &hashed_prefs);
102
103 std::string last_hash;
104 // First try to get the stored expected hash...
105 if (hashed_prefs && hashed_prefs->GetString(path, &last_hash)) {
106 PrefHashCalculator::ValidationResult validation_result =
107 pref_hash_calculator_.Validate(path, initial_value, last_hash);
108 if (validation_result == PrefHashCalculator::VALID)
109 return PrefHashStore::UNCHANGED;
110
111 // No matter what the reason for the mismatch, we will correct it now.
112 pref_hash_tracker_->OnPrefValueChanged(path, initial_value);
113
114 switch(validation_result) {
115 case PrefHashCalculator::VALID_LEGACY:
116 return PrefHashStore::MIGRATED;
117 case PrefHashCalculator::INVALID:
118 return initial_value ? PrefHashStore::CHANGED : PrefHashStore::CLEARED;
119 default:
120 NOTREACHED() << "Unexpected PrefHashCalculator::ValidationResult: "
121 << validation_result;
122 return PrefHashStore::INITIALIZED;
123 }
124 }
125
126 // We haven't tracked this preference yet, or the hash in local state was
127 // removed.
128 pref_hash_tracker_->OnPrefValueChanged(path, initial_value);
129 return PrefHashStore::INITIALIZED;
130 }
131
132 scoped_ptr<PrefHashTracker> PrefHashStoreImpl::CompleteInitialization() {
133 return pref_hash_tracker_.Pass();
134 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698