OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/prefs/pref_service.h" | 5 #include "chrome/browser/prefs/pref_service.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/file_path.h" | 10 #include "base/file_path.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
13 #include "base/metrics/histogram.h" | 13 #include "base/metrics/histogram.h" |
14 #include "base/prefs/default_pref_store.h" | 14 #include "base/prefs/default_pref_store.h" |
15 #include "base/stl_util.h" | 15 #include "base/stl_util.h" |
16 #include "base/string_number_conversions.h" | 16 #include "base/string_number_conversions.h" |
17 #include "base/string_util.h" | 17 #include "base/string_util.h" |
18 #include "base/value_conversions.h" | 18 #include "base/value_conversions.h" |
19 #include "build/build_config.h" | 19 #include "build/build_config.h" |
20 #include "chrome/browser/prefs/pref_notifier_impl.h" | 20 #include "chrome/browser/prefs/pref_notifier_impl.h" |
21 #include "chrome/browser/prefs/pref_registry.h" | |
21 #include "chrome/browser/prefs/pref_value_store.h" | 22 #include "chrome/browser/prefs/pref_value_store.h" |
22 | 23 |
23 using content::BrowserContext; | 24 using content::BrowserContext; |
24 | 25 |
25 namespace { | 26 namespace { |
26 | 27 |
27 class ReadErrorHandler : public PersistentPrefStore::ReadErrorDelegate { | 28 class ReadErrorHandler : public PersistentPrefStore::ReadErrorDelegate { |
28 public: | 29 public: |
29 ReadErrorHandler(base::Callback<void(PersistentPrefStore::PrefReadError)> cb) | 30 ReadErrorHandler(base::Callback<void(PersistentPrefStore::PrefReadError)> cb) |
30 : callback_(cb) {} | 31 : callback_(cb) {} |
31 | 32 |
32 virtual void OnError(PersistentPrefStore::PrefReadError error) { | 33 virtual void OnError(PersistentPrefStore::PrefReadError error) { |
33 callback_.Run(error); | 34 callback_.Run(error); |
34 } | 35 } |
35 | 36 |
36 private: | 37 private: |
37 base::Callback<void(PersistentPrefStore::PrefReadError)> callback_; | 38 base::Callback<void(PersistentPrefStore::PrefReadError)> callback_; |
38 }; | 39 }; |
39 | 40 |
40 } // namespace | 41 } // namespace |
41 | 42 |
42 PrefService::PrefService( | 43 PrefService::PrefService( |
43 PrefNotifierImpl* pref_notifier, | 44 PrefNotifierImpl* pref_notifier, |
44 PrefValueStore* pref_value_store, | 45 PrefValueStore* pref_value_store, |
45 PersistentPrefStore* user_prefs, | 46 PersistentPrefStore* user_prefs, |
46 DefaultPrefStore* default_store, | 47 PrefRegistry* pref_registry, |
47 base::Callback<void(PersistentPrefStore::PrefReadError)> | 48 base::Callback<void(PersistentPrefStore::PrefReadError)> |
48 read_error_callback, | 49 read_error_callback, |
49 bool async) | 50 bool async) |
50 : pref_notifier_(pref_notifier), | 51 : pref_notifier_(pref_notifier), |
51 pref_value_store_(pref_value_store), | 52 pref_value_store_(pref_value_store), |
53 pref_registry_(pref_registry), | |
52 user_pref_store_(user_prefs), | 54 user_pref_store_(user_prefs), |
53 default_store_(default_store), | 55 read_error_callback_(read_error_callback), |
54 read_error_callback_(read_error_callback) { | 56 weak_ptr_factory_(this) { |
55 pref_notifier_->SetPrefService(this); | 57 pref_notifier_->SetPrefService(this); |
58 | |
59 pref_registry_->SetRegistrationCallback( | |
60 base::Bind(&PrefService::AddRegisteredPreference, | |
61 weak_ptr_factory_.GetWeakPtr())); | |
Mattias Nissler (ping if slow)
2013/01/29 18:10:45
Do we need the weak_ptr_factory_ here? We hold a r
Jói
2013/01/30 14:23:33
That would be the alternative. Seems a bit cleaner
| |
62 pref_registry_->SetUnregistrationCallback( | |
63 base::Bind(&PrefService::RemoveRegisteredPreference, | |
64 weak_ptr_factory_.GetWeakPtr())); | |
Mattias Nissler (ping if slow)
2013/01/29 18:10:45
So this will break if we're ever passing a registr
Jói
2013/01/30 14:23:33
Yes, which is why I used the approach you see in p
| |
65 AddInitialPreferences(); | |
66 | |
56 InitFromStorage(async); | 67 InitFromStorage(async); |
57 } | 68 } |
58 | 69 |
59 PrefService::~PrefService() { | 70 PrefService::~PrefService() { |
60 DCHECK(CalledOnValidThread()); | 71 DCHECK(CalledOnValidThread()); |
61 | 72 |
62 // Reset pointers so accesses after destruction reliably crash. | 73 // Reset pointers so accesses after destruction reliably crash. |
63 pref_value_store_.reset(); | 74 pref_value_store_.reset(); |
64 user_pref_store_ = NULL; | 75 user_pref_store_ = NULL; |
65 default_store_ = NULL; | |
66 pref_notifier_.reset(); | 76 pref_notifier_.reset(); |
67 } | 77 } |
68 | 78 |
69 void PrefService::InitFromStorage(bool async) { | 79 void PrefService::InitFromStorage(bool async) { |
70 if (!async) { | 80 if (!async) { |
71 read_error_callback_.Run(user_pref_store_->ReadPrefs()); | 81 read_error_callback_.Run(user_pref_store_->ReadPrefs()); |
72 } else { | 82 } else { |
73 // Guarantee that initialization happens after this function returned. | 83 // Guarantee that initialization happens after this function returned. |
74 MessageLoop::current()->PostTask( | 84 MessageLoop::current()->PostTask( |
75 FROM_HERE, | 85 FROM_HERE, |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
165 } | 175 } |
166 | 176 |
167 bool PrefService::HasPrefPath(const char* path) const { | 177 bool PrefService::HasPrefPath(const char* path) const { |
168 const Preference* pref = FindPreference(path); | 178 const Preference* pref = FindPreference(path); |
169 return pref && !pref->IsDefaultValue(); | 179 return pref && !pref->IsDefaultValue(); |
170 } | 180 } |
171 | 181 |
172 DictionaryValue* PrefService::GetPreferenceValues() const { | 182 DictionaryValue* PrefService::GetPreferenceValues() const { |
173 DCHECK(CalledOnValidThread()); | 183 DCHECK(CalledOnValidThread()); |
174 DictionaryValue* out = new DictionaryValue; | 184 DictionaryValue* out = new DictionaryValue; |
175 DefaultPrefStore::const_iterator i = default_store_->begin(); | 185 PrefRegistry::const_iterator i = pref_registry_->begin(); |
176 for (; i != default_store_->end(); ++i) { | 186 for (; i != pref_registry_->end(); ++i) { |
177 const Value* value = GetPreferenceValue(i->first); | 187 const Value* value = GetPreferenceValue(i->first); |
178 DCHECK(value); | 188 DCHECK(value); |
179 out->Set(i->first, value->DeepCopy()); | 189 out->Set(i->first, value->DeepCopy()); |
180 } | 190 } |
181 return out; | 191 return out; |
182 } | 192 } |
183 | 193 |
184 const PrefService::Preference* PrefService::FindPreference( | 194 const PrefService::Preference* PrefService::FindPreference( |
185 const char* pref_name) const { | 195 const char* pref_name) const { |
186 DCHECK(CalledOnValidThread()); | 196 DCHECK(CalledOnValidThread()); |
187 PreferenceMap::iterator it = prefs_map_.find(pref_name); | 197 PreferenceMap::iterator it = prefs_map_.find(pref_name); |
188 if (it != prefs_map_.end()) | 198 if (it != prefs_map_.end()) |
189 return &(it->second); | 199 return &(it->second); |
190 const base::Value::Type type = default_store_->GetType(pref_name); | 200 const base::Value* default_value = NULL; |
191 if (type == Value::TYPE_NULL) | 201 if (!pref_registry_->defaults()->GetValue(pref_name, &default_value)) |
192 return NULL; | 202 return NULL; |
193 it = prefs_map_.insert( | 203 it = prefs_map_.insert( |
194 std::make_pair(pref_name, Preference(this, pref_name, type))).first; | 204 std::make_pair(pref_name, Preference( |
205 this, pref_name, default_value->GetType()))).first; | |
195 return &(it->second); | 206 return &(it->second); |
196 } | 207 } |
197 | 208 |
198 bool PrefService::ReadOnly() const { | 209 bool PrefService::ReadOnly() const { |
199 return user_pref_store_->ReadOnly(); | 210 return user_pref_store_->ReadOnly(); |
200 } | 211 } |
201 | 212 |
202 PrefService::PrefInitializationStatus PrefService::GetInitializationStatus() | 213 PrefService::PrefInitializationStatus PrefService::GetInitializationStatus() |
203 const { | 214 const { |
204 if (!user_pref_store_->IsInitializationComplete()) | 215 if (!user_pref_store_->IsInitializationComplete()) |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
259 return NULL; | 270 return NULL; |
260 } | 271 } |
261 | 272 |
262 return value; | 273 return value; |
263 } | 274 } |
264 | 275 |
265 const base::Value* PrefService::GetDefaultPrefValue(const char* path) const { | 276 const base::Value* PrefService::GetDefaultPrefValue(const char* path) const { |
266 DCHECK(CalledOnValidThread()); | 277 DCHECK(CalledOnValidThread()); |
267 // Lookup the preference in the default store. | 278 // Lookup the preference in the default store. |
268 const base::Value* value = NULL; | 279 const base::Value* value = NULL; |
269 if (!default_store_->GetValue(path, &value)) { | 280 if (!pref_registry_->defaults()->GetValue(path, &value)) { |
270 NOTREACHED() << "Default value missing for pref: " << path; | 281 NOTREACHED() << "Default value missing for pref: " << path; |
271 return NULL; | 282 return NULL; |
272 } | 283 } |
273 return value; | 284 return value; |
274 } | 285 } |
275 | 286 |
276 const ListValue* PrefService::GetList(const char* path) const { | 287 const ListValue* PrefService::GetList(const char* path) const { |
277 DCHECK(CalledOnValidThread()); | 288 DCHECK(CalledOnValidThread()); |
278 | 289 |
279 const Value* value = GetPreferenceValue(path); | 290 const Value* value = GetPreferenceValue(path); |
(...skipping 13 matching lines...) Expand all Loading... | |
293 } | 304 } |
294 | 305 |
295 void PrefService::RemovePrefObserver(const char* path, PrefObserver* obs) { | 306 void PrefService::RemovePrefObserver(const char* path, PrefObserver* obs) { |
296 pref_notifier_->RemovePrefObserver(path, obs); | 307 pref_notifier_->RemovePrefObserver(path, obs); |
297 } | 308 } |
298 | 309 |
299 void PrefService::AddPrefInitObserver(base::Callback<void(bool)> obs) { | 310 void PrefService::AddPrefInitObserver(base::Callback<void(bool)> obs) { |
300 pref_notifier_->AddInitObserver(obs); | 311 pref_notifier_->AddInitObserver(obs); |
301 } | 312 } |
302 | 313 |
303 void PrefService::RegisterPreference(const char* path, | 314 PrefRegistry* PrefService::DeprecatedGetPrefRegistry() { |
304 Value* default_value) { | 315 return pref_registry_.get(); |
316 } | |
317 | |
318 void PrefService::AddInitialPreferences() { | |
319 for (PrefRegistry::const_iterator it = pref_registry_->begin(); | |
320 it != pref_registry_->end(); | |
321 ++it) { | |
322 AddRegisteredPreference(it->first.c_str(), it->second); | |
323 } | |
324 } | |
325 | |
326 // TODO(joi): Once MarkNeedsEmptyValue is gone, we can probably | |
327 // completely get rid of this method. There will be one difference in | |
328 // semantics; currently all registered preferences are stored right | |
329 // away in the prefs_map_, if we remove this they would be stored only | |
330 // opportunistically. | |
331 void PrefService::AddRegisteredPreference(const char* path, | |
332 Value* default_value) { | |
305 DCHECK(CalledOnValidThread()); | 333 DCHECK(CalledOnValidThread()); |
306 | 334 |
307 // The main code path takes ownership, but most don't. We'll be safe. | 335 // Calling FindPreference here has the side-effect of updating the |
308 scoped_ptr<Value> scoped_value(default_value); | 336 // pref_map_ cache, so all preferences are immediately in the cache. |
309 | 337 bool already_registered = FindPreference(path); |
310 CHECK(!FindPreference(path)) << "Tried to register duplicate pref " << path; | 338 CHECK(!already_registered) << "Tried to register duplicate pref " << path; |
311 | |
312 base::Value::Type orig_type = default_value->GetType(); | |
313 DCHECK(orig_type != Value::TYPE_NULL && orig_type != Value::TYPE_BINARY) << | |
314 "invalid preference type: " << orig_type; | |
315 | 339 |
316 // For ListValue and DictionaryValue with non empty default, empty value | 340 // For ListValue and DictionaryValue with non empty default, empty value |
317 // for |path| needs to be persisted in |user_pref_store_|. So that | 341 // for |path| needs to be persisted in |user_pref_store_|. So that |
318 // non empty default is not used when user sets an empty ListValue or | 342 // non empty default is not used when user sets an empty ListValue or |
319 // DictionaryValue. | 343 // DictionaryValue. |
320 bool needs_empty_value = false; | 344 bool needs_empty_value = false; |
345 base::Value::Type orig_type = default_value->GetType(); | |
321 if (orig_type == base::Value::TYPE_LIST) { | 346 if (orig_type == base::Value::TYPE_LIST) { |
322 const base::ListValue* list = NULL; | 347 const base::ListValue* list = NULL; |
323 if (default_value->GetAsList(&list) && !list->empty()) | 348 if (default_value->GetAsList(&list) && !list->empty()) |
324 needs_empty_value = true; | 349 needs_empty_value = true; |
325 } else if (orig_type == base::Value::TYPE_DICTIONARY) { | 350 } else if (orig_type == base::Value::TYPE_DICTIONARY) { |
326 const base::DictionaryValue* dict = NULL; | 351 const base::DictionaryValue* dict = NULL; |
327 if (default_value->GetAsDictionary(&dict) && !dict->empty()) | 352 if (default_value->GetAsDictionary(&dict) && !dict->empty()) |
328 needs_empty_value = true; | 353 needs_empty_value = true; |
329 } | 354 } |
330 if (needs_empty_value) | 355 if (needs_empty_value) |
331 user_pref_store_->MarkNeedsEmptyValue(path); | 356 user_pref_store_->MarkNeedsEmptyValue(path); |
332 | |
333 // Hand off ownership. | |
334 default_store_->SetDefaultValue(path, scoped_value.release()); | |
335 } | 357 } |
336 | 358 |
337 void PrefService::UnregisterPreference(const char* path) { | 359 // TODO(joi): We can get rid of this once the ability to unregister |
360 // prefs has been removed. | |
361 void PrefService::RemoveRegisteredPreference(const char* path) { | |
338 DCHECK(CalledOnValidThread()); | 362 DCHECK(CalledOnValidThread()); |
339 | 363 |
340 PreferenceMap::iterator it = prefs_map_.find(path); | 364 prefs_map_.erase(path); |
341 CHECK(it != prefs_map_.end()) << "Trying to unregister an unregistered pref: " | |
342 << path; | |
343 | |
344 prefs_map_.erase(it); | |
345 default_store_->RemoveDefaultValue(path); | |
346 } | 365 } |
347 | 366 |
348 void PrefService::ClearPref(const char* path) { | 367 void PrefService::ClearPref(const char* path) { |
349 DCHECK(CalledOnValidThread()); | 368 DCHECK(CalledOnValidThread()); |
350 | 369 |
351 const Preference* pref = FindPreference(path); | 370 const Preference* pref = FindPreference(path); |
352 if (!pref) { | 371 if (!pref) { |
353 NOTREACHED() << "Trying to clear an unregistered pref: " << path; | 372 NOTREACHED() << "Trying to clear an unregistered pref: " << path; |
354 return; | 373 return; |
355 } | 374 } |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
554 return pref_value_store()->PrefValueUserModifiable(name_.c_str()); | 573 return pref_value_store()->PrefValueUserModifiable(name_.c_str()); |
555 } | 574 } |
556 | 575 |
557 bool PrefService::Preference::IsExtensionModifiable() const { | 576 bool PrefService::Preference::IsExtensionModifiable() const { |
558 return pref_value_store()->PrefValueExtensionModifiable(name_.c_str()); | 577 return pref_value_store()->PrefValueExtensionModifiable(name_.c_str()); |
559 } | 578 } |
560 | 579 |
561 const base::Value* PrefService::GetPreferenceValue( | 580 const base::Value* PrefService::GetPreferenceValue( |
562 const std::string& path) const { | 581 const std::string& path) const { |
563 DCHECK(CalledOnValidThread()); | 582 DCHECK(CalledOnValidThread()); |
564 const base::Value::Type type = default_store_->GetType(path); | 583 const Value* default_value = NULL; |
565 if (type == Value::TYPE_NULL) | 584 if (pref_registry_->defaults()->GetValue(path, &default_value)) { |
566 return NULL; | 585 const Value* found_value = NULL; |
567 const Value* found_value = NULL; | 586 base::Value::Type default_type = default_value->GetType(); |
568 if (pref_value_store_->GetValue(path, type, &found_value)) { | 587 if (pref_value_store_->GetValue(path, default_type, &found_value)) { |
569 DCHECK(found_value->IsType(type)); | 588 DCHECK(found_value->IsType(default_type)); |
570 return found_value; | 589 return found_value; |
590 } else { | |
591 // Every registered preference has at least a default value. | |
592 NOTREACHED() << "no valid value found for registered pref " << path; | |
593 } | |
571 } | 594 } |
572 | 595 |
573 // Every registered preference has at least a default value. | |
574 NOTREACHED() << "no valid value found for registered pref " << path; | |
575 return NULL; | 596 return NULL; |
576 } | 597 } |
OLD | NEW |