OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2014 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/tracked/segregated_pref_store.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "base/stl_util.h" | |
9 #include "base/values.h" | |
10 | |
11 SegregatedPrefStore::TeeObserver::TeeObserver(SegregatedPrefStore* outer) | |
12 : outer_(outer), | |
13 failed_sub_initializations_(0), | |
14 successful_sub_initializations_(0) {} | |
15 | |
16 void SegregatedPrefStore::TeeObserver::OnPrefValueChanged( | |
17 const std::string& key) { | |
18 // There is no need to tell clients about changes if they have not yet been | |
19 // told about initialization. | |
robertshield
2014/03/26 21:41:54
Why is it safe to drop these events? (I ask mostly
erikwright (departed)
2014/03/26 21:51:02
The model is as follows:
void X::whatever()
{
st
| |
20 if (failed_sub_initializations_ + successful_sub_initializations_ < 2) | |
21 return; | |
22 | |
23 FOR_EACH_OBSERVER( | |
24 PrefStore::Observer, outer_->observers_, OnPrefValueChanged(key)); | |
25 } | |
26 | |
27 void SegregatedPrefStore::TeeObserver::OnInitializationCompleted( | |
28 bool succeeded) { | |
29 if (succeeded) | |
30 ++successful_sub_initializations_; | |
31 else | |
32 ++failed_sub_initializations_; | |
33 | |
34 DCHECK_LE(failed_sub_initializations_ + successful_sub_initializations_, 2); | |
35 | |
36 if (failed_sub_initializations_ + successful_sub_initializations_ == 2) { | |
37 | |
38 if (!outer_->on_initialization_.is_null()) | |
39 outer_->on_initialization_.Run(); | |
40 | |
41 if (successful_sub_initializations_ == 2 && outer_->read_error_delegate_) { | |
42 PersistentPrefStore::PrefReadError read_error = outer_->GetReadError(); | |
43 if (read_error != PersistentPrefStore::PREF_READ_ERROR_NONE) | |
44 outer_->read_error_delegate_->OnError(read_error); | |
45 } | |
46 | |
47 FOR_EACH_OBSERVER( | |
48 PrefStore::Observer, | |
49 outer_->observers_, | |
50 OnInitializationCompleted(successful_sub_initializations_ == 2)); | |
51 } | |
52 } | |
53 | |
54 SegregatedPrefStore::SegregatedPrefStore( | |
55 const scoped_refptr<PersistentPrefStore>& default_pref_store, | |
56 const scoped_refptr<PersistentPrefStore>& selected_pref_store, | |
57 const std::set<std::string>& selected_pref_names, | |
58 const base::Closure& on_initialization) | |
59 : default_pref_store_(default_pref_store), | |
60 selected_pref_store_(selected_pref_store), | |
61 selected_preference_names_(selected_pref_names), | |
62 on_initialization_(on_initialization), | |
63 tee_observer_(this) { | |
64 | |
65 default_pref_store_->AddObserver(&tee_observer_); | |
66 selected_pref_store_->AddObserver(&tee_observer_); | |
67 } | |
68 | |
69 void SegregatedPrefStore::AddObserver(Observer* observer) { | |
70 observers_.AddObserver(observer); | |
71 } | |
72 | |
73 void SegregatedPrefStore::RemoveObserver(Observer* observer) { | |
74 observers_.RemoveObserver(observer); | |
75 } | |
76 | |
77 bool SegregatedPrefStore::HasObservers() const { | |
78 return observers_.might_have_observers(); | |
79 } | |
80 | |
81 bool SegregatedPrefStore::IsInitializationComplete() const { | |
82 return default_pref_store_->IsInitializationComplete() && | |
83 selected_pref_store_->IsInitializationComplete(); | |
84 } | |
85 | |
86 bool SegregatedPrefStore::GetValue(const std::string& key, | |
87 const base::Value** result) const { | |
88 return StoreForKey(key)->GetValue(key, result); | |
89 } | |
90 | |
91 void SegregatedPrefStore::SetValue(const std::string& key, base::Value* value) { | |
92 StoreForKey(key)->SetValue(key, value); | |
93 } | |
94 | |
95 void SegregatedPrefStore::RemoveValue(const std::string& key) { | |
96 StoreForKey(key)->RemoveValue(key); | |
97 } | |
98 | |
99 bool SegregatedPrefStore::GetMutableValue(const std::string& key, | |
100 base::Value** result) { | |
101 return StoreForKey(key)->GetMutableValue(key, result); | |
102 } | |
103 | |
104 void SegregatedPrefStore::ReportValueChanged(const std::string& key) { | |
105 StoreForKey(key)->ReportValueChanged(key); | |
106 } | |
107 | |
108 void SegregatedPrefStore::SetValueSilently(const std::string& key, | |
109 base::Value* value) { | |
110 StoreForKey(key)->SetValueSilently(key, value); | |
111 } | |
112 | |
113 bool SegregatedPrefStore::ReadOnly() const { | |
114 return selected_pref_store_->ReadOnly() || | |
115 default_pref_store_->ReadOnly(); | |
116 } | |
117 | |
118 PersistentPrefStore::PrefReadError SegregatedPrefStore::GetReadError() const { | |
119 PersistentPrefStore::PrefReadError read_error = | |
120 default_pref_store_->GetReadError(); | |
121 return read_error != PersistentPrefStore::PREF_READ_ERROR_NONE | |
122 ? read_error | |
123 : selected_pref_store_->GetReadError(); | |
124 } | |
125 | |
126 PersistentPrefStore::PrefReadError SegregatedPrefStore::ReadPrefs() { | |
127 PersistentPrefStore::PrefReadError unselected_read_error = | |
128 default_pref_store_->ReadPrefs(); | |
129 PersistentPrefStore::PrefReadError selected_read_error = | |
130 selected_pref_store_->ReadPrefs(); | |
131 | |
132 return unselected_read_error != PersistentPrefStore::PREF_READ_ERROR_NONE | |
133 ? unselected_read_error | |
134 : selected_read_error; | |
135 } | |
136 | |
137 void SegregatedPrefStore::ReadPrefsAsync(ReadErrorDelegate* error_delegate) { | |
138 read_error_delegate_.reset(error_delegate); | |
139 default_pref_store_->ReadPrefsAsync(NULL); | |
140 selected_pref_store_->ReadPrefsAsync(NULL); | |
141 } | |
142 | |
143 void SegregatedPrefStore::CommitPendingWrite() { | |
144 default_pref_store_->CommitPendingWrite(); | |
145 selected_pref_store_->CommitPendingWrite(); | |
146 } | |
147 | |
148 SegregatedPrefStore::~SegregatedPrefStore() { | |
149 default_pref_store_->RemoveObserver(&tee_observer_); | |
150 selected_pref_store_->RemoveObserver(&tee_observer_); | |
151 } | |
152 | |
153 const PersistentPrefStore* | |
154 SegregatedPrefStore::StoreForKey(const std::string& key) const { | |
155 if (ContainsKey(selected_preference_names_, key) || | |
156 selected_pref_store_->GetValue(key, NULL)) { | |
157 return selected_pref_store_.get(); | |
158 } | |
159 return default_pref_store_.get(); | |
160 } | |
161 | |
162 PersistentPrefStore* SegregatedPrefStore::StoreForKey(const std::string& key) { | |
163 if (ContainsKey(selected_preference_names_, key)) | |
164 return selected_pref_store_.get(); | |
165 | |
166 // Check if this unselected value was previously selected. If so, migrate it | |
167 // back to the unselected store. | |
168 // It's hard to do this in a single pass at startup because PrefStore does not | |
169 // permit us to enumerate its contents. | |
170 const base::Value* value = NULL; | |
171 if (selected_pref_store_->GetValue(key, &value)) { | |
172 scoped_ptr<base::Value> migrated_value(value->DeepCopy()); | |
173 value = NULL; | |
174 default_pref_store_->SetValue(key, migrated_value.release()); | |
175 default_pref_store_->CommitPendingWrite(); | |
176 selected_pref_store_->RemoveValue(key); | |
177 selected_pref_store_->CommitPendingWrite(); | |
178 } | |
179 | |
180 return default_pref_store_.get(); | |
181 } | |
OLD | NEW |