| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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/common/pref_service.h" | 5 #include "chrome/common/pref_service.h" |
| 6 | 6 |
| 7 #include "base/compiler_specific.h" | 7 #include "base/compiler_specific.h" |
| 8 #include "base/file_util.h" | 8 #include "base/file_util.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
| 11 #include "base/string_util.h" | 11 #include "base/string_util.h" |
| 12 #include "base/task.h" | 12 #include "base/task.h" |
| 13 #include "base/thread.h" | 13 #include "base/thread.h" |
| 14 #include "chrome/common/json_value_serializer.h" | 14 #include "chrome/common/json_value_serializer.h" |
| 15 #include "chrome/common/l10n_util.h" | 15 #include "chrome/common/l10n_util.h" |
| 16 #include "chrome/common/notification_service.h" | 16 #include "chrome/common/notification_service.h" |
| 17 #include "chrome/common/stl_util-inl.h" | 17 #include "chrome/common/stl_util-inl.h" |
| 18 #include "grit/generated_resources.h" | 18 #include "grit/generated_resources.h" |
| 19 | 19 |
| 20 namespace { | 20 namespace { |
| 21 | 21 |
| 22 // The number of milliseconds we'll wait to do a write of chrome prefs to disk. | 22 // The number of milliseconds we'll wait to do a write of chrome prefs to disk. |
| 23 // This lets us batch together write operations. | 23 // This lets us batch together write operations. |
| 24 static const int kCommitIntervalMs = 10000; | 24 static const int kCommitIntervalMs = 10000; |
| 25 | 25 |
| 26 // Replaces the given file's content with the given data. This allows the | 26 // Replaces the given file's content with the given data. This allows the |
| 27 // preferences to be written to disk on a background thread. | 27 // preferences to be written to disk on a background thread. |
| 28 class SaveLaterTask : public Task { | 28 class SaveLaterTask : public Task { |
| 29 public: | 29 public: |
| 30 SaveLaterTask(const std::wstring& file_name, | 30 SaveLaterTask(const FilePath& file_name, |
| 31 const std::string& data) | 31 const std::string& data) |
| 32 : file_name_(file_name), | 32 : file_name_(file_name), |
| 33 data_(data) { | 33 data_(data) { |
| 34 } | 34 } |
| 35 | 35 |
| 36 void Run() { | 36 void Run() { |
| 37 // Write the data to a temp file then rename to avoid data loss if we crash | 37 // Write the data to a temp file then rename to avoid data loss if we crash |
| 38 // while writing the file. | 38 // while writing the file. |
| 39 std::wstring tmp_file_name = file_name_ + L".tmp"; | 39 FilePath tmp_file_name(file_name_.value() + FILE_PATH_LITERAL(".tmp")); |
| 40 int bytes_written = file_util::WriteFile(tmp_file_name, data_.c_str(), | 40 int bytes_written = file_util::WriteFile(tmp_file_name, data_.c_str(), |
| 41 static_cast<int>(data_.length())); | 41 static_cast<int>(data_.length())); |
| 42 if (bytes_written != -1) { | 42 if (bytes_written != -1) { |
| 43 if (!file_util::Move(tmp_file_name, file_name_)) { | 43 if (!file_util::Move(tmp_file_name, file_name_)) { |
| 44 // Rename failed. Try again on the off chance someone has locked either | 44 // Rename failed. Try again on the off chance someone has locked either |
| 45 // file and hope we're successful the second time through. | 45 // file and hope we're successful the second time through. |
| 46 bool move_result = file_util::Move(tmp_file_name, file_name_); | 46 bool move_result = file_util::Move(tmp_file_name, file_name_); |
| 47 DCHECK(move_result); | 47 DCHECK(move_result); |
| 48 } | 48 } |
| 49 } | 49 } |
| 50 } | 50 } |
| 51 | 51 |
| 52 private: | 52 private: |
| 53 std::wstring file_name_; | 53 FilePath file_name_; |
| 54 std::string data_; | 54 std::string data_; |
| 55 | 55 |
| 56 DISALLOW_COPY_AND_ASSIGN(SaveLaterTask); | 56 DISALLOW_COPY_AND_ASSIGN(SaveLaterTask); |
| 57 }; | 57 }; |
| 58 | 58 |
| 59 // A helper function for RegisterLocalized*Pref that creates a Value* based on | 59 // A helper function for RegisterLocalized*Pref that creates a Value* based on |
| 60 // the string value in the locale dll. Because we control the values in a | 60 // the string value in the locale dll. Because we control the values in a |
| 61 // locale dll, this should always return a Value of the appropriate type. | 61 // locale dll, this should always return a Value of the appropriate type. |
| 62 Value* CreateLocaleDefaultValue(Value::ValueType type, int message_id) { | 62 Value* CreateLocaleDefaultValue(Value::ValueType type, int message_id) { |
| 63 std::wstring resource_string = l10n_util::GetString(message_id); | 63 std::wstring resource_string = l10n_util::GetString(message_id); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 98 } | 98 } |
| 99 | 99 |
| 100 } // namespace | 100 } // namespace |
| 101 | 101 |
| 102 PrefService::PrefService() | 102 PrefService::PrefService() |
| 103 : persistent_(new DictionaryValue), | 103 : persistent_(new DictionaryValue), |
| 104 transient_(new DictionaryValue), | 104 transient_(new DictionaryValue), |
| 105 save_preferences_factory_(NULL) { | 105 save_preferences_factory_(NULL) { |
| 106 } | 106 } |
| 107 | 107 |
| 108 PrefService::PrefService(const std::wstring& pref_filename) | 108 PrefService::PrefService(const FilePath& pref_filename) |
| 109 : persistent_(new DictionaryValue), | 109 : persistent_(new DictionaryValue), |
| 110 transient_(new DictionaryValue), | 110 transient_(new DictionaryValue), |
| 111 pref_filename_(pref_filename), | 111 pref_filename_(pref_filename), |
| 112 ALLOW_THIS_IN_INITIALIZER_LIST(save_preferences_factory_(this)) { | 112 ALLOW_THIS_IN_INITIALIZER_LIST(save_preferences_factory_(this)) { |
| 113 LoadPersistentPrefs(pref_filename_); | 113 LoadPersistentPrefs(pref_filename_); |
| 114 } | 114 } |
| 115 | 115 |
| 116 PrefService::~PrefService() { | 116 PrefService::~PrefService() { |
| 117 DCHECK(CalledOnValidThread()); | 117 DCHECK(CalledOnValidThread()); |
| 118 | 118 |
| 119 // Verify that there are no pref observers when we shut down. | 119 // Verify that there are no pref observers when we shut down. |
| 120 for (PrefObserverMap::iterator it = pref_observers_.begin(); | 120 for (PrefObserverMap::iterator it = pref_observers_.begin(); |
| 121 it != pref_observers_.end(); ++it) { | 121 it != pref_observers_.end(); ++it) { |
| 122 NotificationObserverList::Iterator obs_iterator(*(it->second)); | 122 NotificationObserverList::Iterator obs_iterator(*(it->second)); |
| 123 if (obs_iterator.GetNext()) { | 123 if (obs_iterator.GetNext()) { |
| 124 LOG(WARNING) << "pref observer found at shutdown " << it->first; | 124 LOG(WARNING) << "pref observer found at shutdown " << it->first; |
| 125 } | 125 } |
| 126 } | 126 } |
| 127 | 127 |
| 128 STLDeleteContainerPointers(prefs_.begin(), prefs_.end()); | 128 STLDeleteContainerPointers(prefs_.begin(), prefs_.end()); |
| 129 prefs_.clear(); | 129 prefs_.clear(); |
| 130 STLDeleteContainerPairSecondPointers(pref_observers_.begin(), | 130 STLDeleteContainerPairSecondPointers(pref_observers_.begin(), |
| 131 pref_observers_.end()); | 131 pref_observers_.end()); |
| 132 pref_observers_.clear(); | 132 pref_observers_.clear(); |
| 133 } | 133 } |
| 134 | 134 |
| 135 bool PrefService::LoadPersistentPrefs(const std::wstring& file_path) { | 135 bool PrefService::LoadPersistentPrefs(const FilePath& file_path) { |
| 136 #if defined(OS_WIN) | 136 #if defined(OS_WIN) |
| 137 DCHECK(!file_path.empty()); | 137 DCHECK(!file_path.empty()); |
| 138 #else | 138 #else |
| 139 // On non-Windows platforms we haven't gotten round to this yet. | 139 // On non-Windows platforms we haven't gotten round to this yet. |
| 140 // TODO(port): remove this exception | 140 // TODO(port): remove this exception |
| 141 if (file_path.empty()) { | 141 if (file_path.empty()) { |
| 142 NOTIMPLEMENTED(); | 142 NOTIMPLEMENTED(); |
| 143 return false; | 143 return false; |
| 144 } | 144 } |
| 145 #endif | 145 #endif |
| 146 DCHECK(CalledOnValidThread()); | 146 DCHECK(CalledOnValidThread()); |
| 147 | 147 |
| 148 JSONFileValueSerializer serializer(file_path); | 148 JSONFileValueSerializer serializer(file_path.ToWStringHack()); |
| 149 scoped_ptr<Value> root(serializer.Deserialize(NULL)); | 149 scoped_ptr<Value> root(serializer.Deserialize(NULL)); |
| 150 if (!root.get()) | 150 if (!root.get()) |
| 151 return false; | 151 return false; |
| 152 | 152 |
| 153 // Preferences should always have a dictionary root. | 153 // Preferences should always have a dictionary root. |
| 154 if (!root->IsType(Value::TYPE_DICTIONARY)) | 154 if (!root->IsType(Value::TYPE_DICTIONARY)) |
| 155 return false; | 155 return false; |
| 156 | 156 |
| 157 persistent_.reset(static_cast<DictionaryValue*>(root.release())); | 157 persistent_.reset(static_cast<DictionaryValue*>(root.release())); |
| 158 return true; | 158 return true; |
| 159 } | 159 } |
| 160 | 160 |
| 161 void PrefService::ReloadPersistentPrefs() { | 161 void PrefService::ReloadPersistentPrefs() { |
| 162 DCHECK(CalledOnValidThread()); | 162 DCHECK(CalledOnValidThread()); |
| 163 | 163 |
| 164 JSONFileValueSerializer serializer(pref_filename_); | 164 JSONFileValueSerializer serializer(pref_filename_.ToWStringHack()); |
| 165 scoped_ptr<Value> root(serializer.Deserialize(NULL)); | 165 scoped_ptr<Value> root(serializer.Deserialize(NULL)); |
| 166 if (!root.get()) | 166 if (!root.get()) |
| 167 return; | 167 return; |
| 168 | 168 |
| 169 // Preferences should always have a dictionary root. | 169 // Preferences should always have a dictionary root. |
| 170 if (!root->IsType(Value::TYPE_DICTIONARY)) | 170 if (!root->IsType(Value::TYPE_DICTIONARY)) |
| 171 return; | 171 return; |
| 172 | 172 |
| 173 persistent_.reset(static_cast<DictionaryValue*>(root.release())); | 173 persistent_.reset(static_cast<DictionaryValue*>(root.release())); |
| 174 for (PreferenceSet::iterator it = prefs_.begin(); | 174 for (PreferenceSet::iterator it = prefs_.begin(); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 232 RegisterPreference(pref); | 232 RegisterPreference(pref); |
| 233 } | 233 } |
| 234 | 234 |
| 235 void PrefService::RegisterStringPref(const wchar_t* path, | 235 void PrefService::RegisterStringPref(const wchar_t* path, |
| 236 const std::wstring& default_value) { | 236 const std::wstring& default_value) { |
| 237 Preference* pref = new Preference(persistent_.get(), path, | 237 Preference* pref = new Preference(persistent_.get(), path, |
| 238 Value::CreateStringValue(default_value)); | 238 Value::CreateStringValue(default_value)); |
| 239 RegisterPreference(pref); | 239 RegisterPreference(pref); |
| 240 } | 240 } |
| 241 | 241 |
| 242 void PrefService::RegisterFilePathPref(const wchar_t* path, |
| 243 const FilePath& default_value) { |
| 244 Preference* pref = new Preference(persistent_.get(), path, |
| 245 Value::CreateStringValue(default_value.value())); |
| 246 RegisterPreference(pref); |
| 247 } |
| 248 |
| 242 void PrefService::RegisterListPref(const wchar_t* path) { | 249 void PrefService::RegisterListPref(const wchar_t* path) { |
| 243 Preference* pref = new Preference(persistent_.get(), path, | 250 Preference* pref = new Preference(persistent_.get(), path, |
| 244 new ListValue); | 251 new ListValue); |
| 245 RegisterPreference(pref); | 252 RegisterPreference(pref); |
| 246 } | 253 } |
| 247 | 254 |
| 248 void PrefService::RegisterDictionaryPref(const wchar_t* path) { | 255 void PrefService::RegisterDictionaryPref(const wchar_t* path) { |
| 249 Preference* pref = new Preference(persistent_.get(), path, | 256 Preference* pref = new Preference(persistent_.get(), path, |
| 250 new DictionaryValue()); | 257 new DictionaryValue()); |
| 251 RegisterPreference(pref); | 258 RegisterPreference(pref); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 350 #else | 357 #else |
| 351 // TODO(port): remove this exception | 358 // TODO(port): remove this exception |
| 352 #endif | 359 #endif |
| 353 return result; | 360 return result; |
| 354 } | 361 } |
| 355 bool rv = pref->GetValue()->GetAsString(&result); | 362 bool rv = pref->GetValue()->GetAsString(&result); |
| 356 DCHECK(rv); | 363 DCHECK(rv); |
| 357 return result; | 364 return result; |
| 358 } | 365 } |
| 359 | 366 |
| 367 FilePath PrefService::GetFilePath(const wchar_t* path) const { |
| 368 DCHECK(CalledOnValidThread()); |
| 369 |
| 370 FilePath::StringType result; |
| 371 if (transient_->GetString(path, &result)) |
| 372 return FilePath(result); |
| 373 |
| 374 const Preference* pref = FindPreference(path); |
| 375 if (!pref) { |
| 376 #if defined(OS_WIN) |
| 377 DCHECK(false) << "Trying to read an unregistered pref: " << path; |
| 378 #else |
| 379 // TODO(port): remove this exception |
| 380 #endif |
| 381 return FilePath(result); |
| 382 } |
| 383 bool rv = pref->GetValue()->GetAsString(&result); |
| 384 DCHECK(rv); |
| 385 return FilePath(result); |
| 386 } |
| 387 |
| 360 bool PrefService::HasPrefPath(const wchar_t* path) const { | 388 bool PrefService::HasPrefPath(const wchar_t* path) const { |
| 361 Value* value = NULL; | 389 Value* value = NULL; |
| 362 return (transient_->Get(path, &value) || persistent_->Get(path, &value)); | 390 return (transient_->Get(path, &value) || persistent_->Get(path, &value)); |
| 363 } | 391 } |
| 364 | 392 |
| 365 const PrefService::Preference* PrefService::FindPreference( | 393 const PrefService::Preference* PrefService::FindPreference( |
| 366 const wchar_t* pref_name) const { | 394 const wchar_t* pref_name) const { |
| 367 DCHECK(CalledOnValidThread()); | 395 DCHECK(CalledOnValidThread()); |
| 368 Preference p(NULL, pref_name, NULL); | 396 Preference p(NULL, pref_name, NULL); |
| 369 PreferenceSet::const_iterator it = prefs_.find(&p); | 397 PreferenceSet::const_iterator it = prefs_.find(&p); |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 555 return; | 583 return; |
| 556 } | 584 } |
| 557 | 585 |
| 558 scoped_ptr<Value> old_value(GetPrefCopy(path)); | 586 scoped_ptr<Value> old_value(GetPrefCopy(path)); |
| 559 bool rv = persistent_->SetString(path, value); | 587 bool rv = persistent_->SetString(path, value); |
| 560 DCHECK(rv); | 588 DCHECK(rv); |
| 561 | 589 |
| 562 FireObserversIfChanged(path, old_value.get()); | 590 FireObserversIfChanged(path, old_value.get()); |
| 563 } | 591 } |
| 564 | 592 |
| 593 void PrefService::SetFilePath(const wchar_t* path, const FilePath& value) { |
| 594 DCHECK(CalledOnValidThread()); |
| 595 |
| 596 const Preference* pref = FindPreference(path); |
| 597 if (!pref) { |
| 598 DCHECK(false) << "Trying to write an unregistered pref: " << path; |
| 599 return; |
| 600 } |
| 601 if (pref->type() != Value::TYPE_STRING) { |
| 602 DCHECK(false) << "Wrong type for SetFilePath: " << path; |
| 603 return; |
| 604 } |
| 605 |
| 606 scoped_ptr<Value> old_value(GetPrefCopy(path)); |
| 607 bool rv = persistent_->SetString(path, value.value()); |
| 608 DCHECK(rv); |
| 609 |
| 610 FireObserversIfChanged(path, old_value.get()); |
| 611 } |
| 612 |
| 565 DictionaryValue* PrefService::GetMutableDictionary(const wchar_t* path) { | 613 DictionaryValue* PrefService::GetMutableDictionary(const wchar_t* path) { |
| 566 DCHECK(CalledOnValidThread()); | 614 DCHECK(CalledOnValidThread()); |
| 567 | 615 |
| 568 const Preference* pref = FindPreference(path); | 616 const Preference* pref = FindPreference(path); |
| 569 if (!pref) { | 617 if (!pref) { |
| 570 DCHECK(false) << "Trying to get an unregistered pref: " << path; | 618 DCHECK(false) << "Trying to get an unregistered pref: " << path; |
| 571 return NULL; | 619 return NULL; |
| 572 } | 620 } |
| 573 if (pref->type() != Value::TYPE_DICTIONARY) { | 621 if (pref->type() != Value::TYPE_DICTIONARY) { |
| 574 DCHECK(false) << "Wrong type for GetMutableDictionary: " << path; | 622 DCHECK(false) << "Wrong type for GetMutableDictionary: " << path; |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 678 } | 726 } |
| 679 | 727 |
| 680 // Pref not found, just return the app default. | 728 // Pref not found, just return the app default. |
| 681 return default_value_.get(); | 729 return default_value_.get(); |
| 682 } | 730 } |
| 683 | 731 |
| 684 bool PrefService::Preference::IsDefaultValue() const { | 732 bool PrefService::Preference::IsDefaultValue() const { |
| 685 DCHECK(default_value_.get()); | 733 DCHECK(default_value_.get()); |
| 686 return default_value_->Equals(GetValue()); | 734 return default_value_->Equals(GetValue()); |
| 687 } | 735 } |
| OLD | NEW |