diff options
Diffstat (limited to 'chrome/common')
-rw-r--r-- | chrome/common/important_file_writer.cc | 143 | ||||
-rw-r--r-- | chrome/common/important_file_writer.h | 104 | ||||
-rw-r--r-- | chrome/common/important_file_writer_unittest.cc | 113 | ||||
-rw-r--r-- | chrome/common/pref_member.cc | 87 | ||||
-rw-r--r-- | chrome/common/pref_member.h | 176 | ||||
-rw-r--r-- | chrome/common/pref_member_unittest.cc | 193 | ||||
-rw-r--r-- | chrome/common/pref_service.cc | 684 | ||||
-rw-r--r-- | chrome/common/pref_service.h | 222 | ||||
-rw-r--r-- | chrome/common/pref_service_uitest.cc | 133 | ||||
-rw-r--r-- | chrome/common/pref_service_unittest.cc | 270 |
10 files changed, 0 insertions, 2125 deletions
diff --git a/chrome/common/important_file_writer.cc b/chrome/common/important_file_writer.cc deleted file mode 100644 index 1759116..0000000 --- a/chrome/common/important_file_writer.cc +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/common/important_file_writer.h" - -#include <stdio.h> - -#include <ostream> -#include <string> - -#include "base/file_path.h" -#include "base/file_util.h" -#include "base/logging.h" -#include "base/string_util.h" -#include "base/task.h" -#include "base/thread.h" -#include "base/time.h" -#include "chrome/browser/chrome_thread.h" - -using base::TimeDelta; - -namespace { - -const int kDefaultCommitIntervalMs = 10000; - -class WriteToDiskTask : public Task { - public: - WriteToDiskTask(const FilePath& path, const std::string& data) - : path_(path), - data_(data) { - } - - virtual void Run() { - // Write the data to a temp file then rename to avoid data loss if we crash - // while writing the file. Ensure that the temp file is on the same volume - // as target file, so it can be moved in one step, and that the temp file - // is securely created. - FilePath tmp_file_path; - FILE* tmp_file = file_util::CreateAndOpenTemporaryFileInDir( - path_.DirName(), &tmp_file_path); - if (!tmp_file) { - LogFailure("could not create temporary file"); - return; - } - - size_t bytes_written = fwrite(data_.data(), 1, data_.length(), tmp_file); - if (!file_util::CloseFile(tmp_file)) { - file_util::Delete(tmp_file_path, false); - LogFailure("failed to close temporary file"); - return; - } - if (bytes_written < data_.length()) { - file_util::Delete(tmp_file_path, false); - LogFailure("error writing, bytes_written=" + UintToString(bytes_written)); - return; - } - - if (file_util::ReplaceFile(tmp_file_path, path_)) { - LogSuccess(); - return; - } - - file_util::Delete(tmp_file_path, false); - LogFailure("could not rename temporary file"); - } - - private: - void LogSuccess() { - LOG(INFO) << "successfully saved " << path_.value(); - } - - void LogFailure(const std::string& message) { - LOG(WARNING) << "failed to write " << path_.value() - << ": " << message; - } - - const FilePath path_; - const std::string data_; - - DISALLOW_COPY_AND_ASSIGN(WriteToDiskTask); -}; - -} // namespace - -ImportantFileWriter::ImportantFileWriter(const FilePath& path) - : path_(path), - serializer_(NULL), - commit_interval_(TimeDelta::FromMilliseconds(kDefaultCommitIntervalMs)) { - DCHECK(CalledOnValidThread()); -} - -ImportantFileWriter::~ImportantFileWriter() { - // We're usually a member variable of some other object, which also tends - // to be our serializer. It may not be safe to call back to the parent object - // being destructed. - DCHECK(!HasPendingWrite()); -} - -bool ImportantFileWriter::HasPendingWrite() const { - DCHECK(CalledOnValidThread()); - return timer_.IsRunning(); -} - -void ImportantFileWriter::WriteNow(const std::string& data) { - DCHECK(CalledOnValidThread()); - - if (HasPendingWrite()) - timer_.Stop(); - - ChromeThread::PostTask( - ChromeThread::FILE, FROM_HERE, new WriteToDiskTask(path_, data)); -} - -void ImportantFileWriter::ScheduleWrite(DataSerializer* serializer) { - DCHECK(CalledOnValidThread()); - - DCHECK(serializer); - serializer_ = serializer; - - if (!MessageLoop::current()) { - // Happens in unit tests. - DoScheduledWrite(); - return; - } - - if (!timer_.IsRunning()) { - timer_.Start(commit_interval_, this, - &ImportantFileWriter::DoScheduledWrite); - } -} - -void ImportantFileWriter::DoScheduledWrite() { - DCHECK(serializer_); - std::string data; - if (serializer_->SerializeData(&data)) { - WriteNow(data); - } else { - LOG(WARNING) << "failed to serialize data to be saved in " - << path_.value(); - } - serializer_ = NULL; -} diff --git a/chrome/common/important_file_writer.h b/chrome/common/important_file_writer.h deleted file mode 100644 index 4b70622..0000000 --- a/chrome/common/important_file_writer.h +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_COMMON_IMPORTANT_FILE_WRITER_H_ -#define CHROME_COMMON_IMPORTANT_FILE_WRITER_H_ - -#include <string> - -#include "base/basictypes.h" -#include "base/file_path.h" -#include "base/non_thread_safe.h" -#include "base/time.h" -#include "base/timer.h" - -namespace base { -class Thread; -} - -// Helper to ensure that a file won't be corrupted by the write (for example on -// application crash). Consider a naive way to save an important file F: -// -// 1. Open F for writing, truncating it. -// 2. Write new data to F. -// -// It's good when it works, but it gets very bad if step 2. doesn't complete. -// It can be caused by a crash, a computer hang, or a weird I/O error. And you -// end up with a broken file. -// -// To be safe, we don't start with writing directly to F. Instead, we write to -// to a temporary file. Only after that write is successful, we rename the -// temporary file to target filename. -// -// If you want to know more about this approach and ext3/ext4 fsync issues, see -// http://valhenson.livejournal.com/37921.html -class ImportantFileWriter : public NonThreadSafe { - public: - // Used by ScheduleSave to lazily provide the data to be saved. Allows us - // to also batch data serializations. - class DataSerializer { - public: - virtual ~DataSerializer() {} - - // Should put serialized string in |data| and return true on successful - // serialization. Will be called on the same thread on which - // ImportantFileWriter has been created. - virtual bool SerializeData(std::string* data) = 0; - }; - - // Initialize the writer. - // |path| is the name of file to write. - // All non-const methods, ctor and dtor must be called on the same thread. - explicit ImportantFileWriter(const FilePath& path); - - // You have to ensure that there are no pending writes at the moment - // of destruction. - ~ImportantFileWriter(); - - FilePath path() const { return path_; } - - // Returns true if there is a scheduled write pending which has not yet - // been started. - bool HasPendingWrite() const; - - // Save |data| to target filename. Does not block. If there is a pending write - // scheduled by ScheduleWrite, it is cancelled. - void WriteNow(const std::string& data); - - // Schedule a save to target filename. Data will be serialized and saved - // to disk after the commit interval. If another ScheduleWrite is issued - // before that, only one serialization and write to disk will happen, and - // the most recent |serializer| will be used. This operation does not block. - // |serializer| should remain valid through the lifetime of - // ImportantFileWriter. - void ScheduleWrite(DataSerializer* serializer); - - // Serialize data pending to be saved and execute write on backend thread. - void DoScheduledWrite(); - - base::TimeDelta commit_interval() const { - return commit_interval_; - } - - void set_commit_interval(const base::TimeDelta& interval) { - commit_interval_ = interval; - } - - private: - // Path being written to. - const FilePath path_; - - // Timer used to schedule commit after ScheduleWrite. - base::OneShotTimer<ImportantFileWriter> timer_; - - // Serializer which will provide the data to be saved. - DataSerializer* serializer_; - - // Time delta after which scheduled data will be written to disk. - base::TimeDelta commit_interval_; - - DISALLOW_COPY_AND_ASSIGN(ImportantFileWriter); -}; - -#endif // CHROME_COMMON_IMPORTANT_FILE_WRITER_H_ diff --git a/chrome/common/important_file_writer_unittest.cc b/chrome/common/important_file_writer_unittest.cc deleted file mode 100644 index b3fee0d..0000000 --- a/chrome/common/important_file_writer_unittest.cc +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/common/important_file_writer.h" - -#include "base/compiler_specific.h" -#include "base/file_path.h" -#include "base/file_util.h" -#include "base/logging.h" -#include "base/message_loop.h" -#include "base/scoped_temp_dir.h" -#include "base/thread.h" -#include "base/time.h" -#include "chrome/browser/chrome_thread.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -std::string GetFileContent(const FilePath& path) { - std::string content; - if (!file_util::ReadFileToString(path, &content)) { - NOTREACHED(); - } - return content; -} - -class DataSerializer : public ImportantFileWriter::DataSerializer { - public: - explicit DataSerializer(const std::string& data) : data_(data) { - } - - virtual bool SerializeData(std::string* output) { - output->assign(data_); - return true; - } - - private: - const std::string data_; -}; - -} // namespace - -class ImportantFileWriterTest : public testing::Test { - public: - ImportantFileWriterTest() : file_thread_(ChromeThread::FILE, &loop_) { } - virtual void SetUp() { - ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); - file_ = temp_dir_.path().AppendASCII("test-file"); - } - - protected: - FilePath file_; - MessageLoop loop_; - - private: - ChromeThread file_thread_; - ScopedTempDir temp_dir_; -}; - -TEST_F(ImportantFileWriterTest, Basic) { - ImportantFileWriter writer(file_); - EXPECT_FALSE(file_util::PathExists(writer.path())); - writer.WriteNow("foo"); - loop_.RunAllPending(); - - ASSERT_TRUE(file_util::PathExists(writer.path())); - EXPECT_EQ("foo", GetFileContent(writer.path())); -} - -TEST_F(ImportantFileWriterTest, ScheduleWrite) { - ImportantFileWriter writer(file_); - writer.set_commit_interval(base::TimeDelta::FromMilliseconds(25)); - EXPECT_FALSE(writer.HasPendingWrite()); - DataSerializer serializer("foo"); - writer.ScheduleWrite(&serializer); - EXPECT_TRUE(writer.HasPendingWrite()); - MessageLoop::current()->PostDelayedTask(FROM_HERE, - new MessageLoop::QuitTask(), 100); - MessageLoop::current()->Run(); - EXPECT_FALSE(writer.HasPendingWrite()); - ASSERT_TRUE(file_util::PathExists(writer.path())); - EXPECT_EQ("foo", GetFileContent(writer.path())); -} - -TEST_F(ImportantFileWriterTest, DoScheduledWrite) { - ImportantFileWriter writer(file_); - EXPECT_FALSE(writer.HasPendingWrite()); - DataSerializer serializer("foo"); - writer.ScheduleWrite(&serializer); - EXPECT_TRUE(writer.HasPendingWrite()); - writer.DoScheduledWrite(); - MessageLoop::current()->PostDelayedTask(FROM_HERE, - new MessageLoop::QuitTask(), 100); - MessageLoop::current()->Run(); - EXPECT_FALSE(writer.HasPendingWrite()); - ASSERT_TRUE(file_util::PathExists(writer.path())); - EXPECT_EQ("foo", GetFileContent(writer.path())); -} - -TEST_F(ImportantFileWriterTest, BatchingWrites) { - ImportantFileWriter writer(file_); - writer.set_commit_interval(base::TimeDelta::FromMilliseconds(25)); - DataSerializer foo("foo"), bar("bar"), baz("baz"); - writer.ScheduleWrite(&foo); - writer.ScheduleWrite(&bar); - writer.ScheduleWrite(&baz); - MessageLoop::current()->PostDelayedTask(FROM_HERE, - new MessageLoop::QuitTask(), 100); - MessageLoop::current()->Run(); - ASSERT_TRUE(file_util::PathExists(writer.path())); - EXPECT_EQ("baz", GetFileContent(writer.path())); -} diff --git a/chrome/common/pref_member.cc b/chrome/common/pref_member.cc deleted file mode 100644 index 9ae0842..0000000 --- a/chrome/common/pref_member.cc +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/common/pref_member.h" - -#include "base/logging.h" -#include "chrome/common/notification_type.h" -#include "chrome/common/pref_service.h" - -namespace subtle { - -PrefMemberBase::PrefMemberBase() - : observer_(NULL), - prefs_(NULL), - is_synced_(false), - setting_value_(false) { -} - -PrefMemberBase::~PrefMemberBase() { - if (!pref_name_.empty()) - prefs_->RemovePrefObserver(pref_name_.c_str(), this); -} - - -void PrefMemberBase::Init(const wchar_t* pref_name, PrefService* prefs, - NotificationObserver* observer) { - DCHECK(pref_name); - DCHECK(prefs); - DCHECK(pref_name_.empty()); // Check that Init is only called once. - observer_ = observer; - prefs_ = prefs; - pref_name_ = pref_name; - DCHECK(!pref_name_.empty()); - - // Add ourself as a pref observer so we can keep our local value in sync. - prefs_->AddPrefObserver(pref_name, this); -} - -void PrefMemberBase::Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - DCHECK(!pref_name_.empty()); - DCHECK(NotificationType::PREF_CHANGED == type); - UpdateValueFromPref(); - is_synced_ = true; - if (!setting_value_ && observer_) - observer_->Observe(type, source, details); -} - -void PrefMemberBase::VerifyValuePrefName() { - DCHECK(!pref_name_.empty()); -} - -} // namespace subtle - -void BooleanPrefMember::UpdateValueFromPref() { - value_ = prefs()->GetBoolean(pref_name().c_str()); -} - -void BooleanPrefMember::UpdatePref(const bool& value) { - prefs()->SetBoolean(pref_name().c_str(), value); -} - -void IntegerPrefMember::UpdateValueFromPref() { - value_ = prefs()->GetInteger(pref_name().c_str()); -} - -void IntegerPrefMember::UpdatePref(const int& value) { - prefs()->SetInteger(pref_name().c_str(), value); -} - -void RealPrefMember::UpdateValueFromPref() { - value_ = prefs()->GetReal(pref_name().c_str()); -} - -void RealPrefMember::UpdatePref(const double& value) { - prefs()->SetReal(pref_name().c_str(), value); -} - -void StringPrefMember::UpdateValueFromPref() { - value_ = prefs()->GetString(pref_name().c_str()); -} - -void StringPrefMember::UpdatePref(const std::wstring& value) { - prefs()->SetString(pref_name().c_str(), value); -} diff --git a/chrome/common/pref_member.h b/chrome/common/pref_member.h deleted file mode 100644 index 4b96907..0000000 --- a/chrome/common/pref_member.h +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// A helper class that stays in sync with a preference (bool, int, real, or -// string). For example: -// -// class MyClass { -// public: -// MyClass(PrefService* prefs) { -// my_string_.Init(prefs::kHomePage, prefs, NULL /* no observer */); -// } -// private: -// StringPrefMember my_string_; -// }; -// -// my_string_ should stay in sync with the prefs::kHomePage pref and will -// update if either the pref changes or if my_string_.SetValue is called. -// -// An optional observer can be passed into the Init method which can be used to -// notify MyClass of changes. Note that if you use SetValue(), the observer -// will not be notified. - -#ifndef CHROME_COMMON_PREF_MEMBER_H_ -#define CHROME_COMMON_PREF_MEMBER_H_ - -#include <string> - -#include "base/basictypes.h" -#include "chrome/common/notification_observer.h" - -class PrefService; - -namespace subtle { - -class PrefMemberBase : public NotificationObserver { - protected: - PrefMemberBase(); - virtual ~PrefMemberBase(); - - // See PrefMember<> for description. - void Init(const wchar_t* pref_name, PrefService* prefs, - NotificationObserver* observer); - - // NotificationObserver - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details); - - void VerifyValuePrefName(); - - // This methods is used to do the actual sync with pref of the specified type. - virtual void UpdateValueFromPref() = 0; - - const std::wstring& pref_name() const { return pref_name_; } - PrefService* prefs() { return prefs_; } - - // Ordered the members to compact the class instance. - private: - std::wstring pref_name_; - NotificationObserver* observer_; - PrefService* prefs_; - - protected: - bool is_synced_; - bool setting_value_; -}; - -} // namespace subtle - - -template <typename ValueType> -class PrefMember : public subtle::PrefMemberBase { - public: - // Defer initialization to an Init method so it's easy to make this class be - // a member variable. - PrefMember() { } - virtual ~PrefMember() { } - - // Do the actual initialization of the class. |observer| may be null if you - // don't want any notifications of changes. - void Init(const wchar_t* pref_name, PrefService* prefs, - NotificationObserver* observer) { - subtle::PrefMemberBase::Init(pref_name, prefs, observer); - } - - // Retrieve the value of the member variable. - ValueType GetValue() { - VerifyValuePrefName(); - // We lazily fetch the value from the pref service the first time GetValue - // is called. - if (!is_synced_) { - UpdateValueFromPref(); - is_synced_ = true; - } - return value_; - } - - // Provided as a convenience. - ValueType operator*() { - return GetValue(); - } - - // Set the value of the member variable. - void SetValue(const ValueType& value) { - VerifyValuePrefName(); - setting_value_ = true; - UpdatePref(value); - setting_value_ = false; - } - - protected: - // This methods is used to do the actual sync with pref of the specified type. - virtual void UpdatePref(const ValueType& value) = 0; - - // We cache the value of the pref so we don't have to keep walking the pref - // tree. - ValueType value_; -}; - -/////////////////////////////////////////////////////////////////////////////// -// Implementations of Boolean, Integer, Real, and String PrefMember below. - -class BooleanPrefMember : public PrefMember<bool> { - public: - BooleanPrefMember() : PrefMember<bool>() { } - virtual ~BooleanPrefMember() { } - - protected: - virtual void UpdateValueFromPref(); - virtual void UpdatePref(const bool& value); - - private: - DISALLOW_COPY_AND_ASSIGN(BooleanPrefMember); -}; - -class IntegerPrefMember : public PrefMember<int> { - public: - IntegerPrefMember() : PrefMember<int>() { } - virtual ~IntegerPrefMember() { } - - protected: - virtual void UpdateValueFromPref(); - virtual void UpdatePref(const int& value); - - private: - DISALLOW_COPY_AND_ASSIGN(IntegerPrefMember); -}; - -class RealPrefMember : public PrefMember<double> { - public: - RealPrefMember() : PrefMember<double>() { } - virtual ~RealPrefMember() { } - - protected: - virtual void UpdateValueFromPref(); - virtual void UpdatePref(const double& value); - - private: - DISALLOW_COPY_AND_ASSIGN(RealPrefMember); -}; - -class StringPrefMember : public PrefMember<std::wstring> { - public: - StringPrefMember() : PrefMember<std::wstring>() { } - virtual ~StringPrefMember() { } - - protected: - virtual void UpdateValueFromPref(); - virtual void UpdatePref(const std::wstring& value); - - private: - DISALLOW_COPY_AND_ASSIGN(StringPrefMember); -}; - -#endif // CHROME_COMMON_PREF_MEMBER_H_ diff --git a/chrome/common/pref_member_unittest.cc b/chrome/common/pref_member_unittest.cc deleted file mode 100644 index 732708e..0000000 --- a/chrome/common/pref_member_unittest.cc +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/file_path.h" -#include "chrome/common/notification_service.h" -#include "chrome/common/pref_member.h" -#include "chrome/common/pref_service.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -static const wchar_t kBoolPref[] = L"bool"; -static const wchar_t kIntPref[] = L"int"; -static const wchar_t kRealPref[] = L"real"; -static const wchar_t kStringPref[] = L"string"; - -void RegisterTestPrefs(PrefService* prefs) { - prefs->RegisterBooleanPref(kBoolPref, false); - prefs->RegisterIntegerPref(kIntPref, 0); - prefs->RegisterRealPref(kRealPref, 0.0); - prefs->RegisterStringPref(kStringPref, L"default"); -} - -class PrefMemberTestClass : public NotificationObserver { - public: - explicit PrefMemberTestClass(PrefService* prefs) - : observe_cnt_(0), prefs_(prefs) { - str_.Init(kStringPref, prefs, this); - } - - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - DCHECK(NotificationType::PREF_CHANGED == type); - PrefService* prefs_in = Source<PrefService>(source).ptr(); - EXPECT_EQ(prefs_in, prefs_); - std::wstring* pref_name_in = Details<std::wstring>(details).ptr(); - EXPECT_EQ(*pref_name_in, kStringPref); - EXPECT_EQ(str_.GetValue(), prefs_->GetString(kStringPref)); - ++observe_cnt_; - } - - StringPrefMember str_; - int observe_cnt_; - - private: - PrefService* prefs_; -}; - -} // anonymous namespace - -TEST(PrefMemberTest, BasicGetAndSet) { - PrefService prefs((FilePath())); - RegisterTestPrefs(&prefs); - - // Test bool - BooleanPrefMember boolean; - boolean.Init(kBoolPref, &prefs, NULL); - - // Check the defaults - EXPECT_FALSE(prefs.GetBoolean(kBoolPref)); - EXPECT_FALSE(boolean.GetValue()); - EXPECT_FALSE(*boolean); - - // Try changing through the member variable. - boolean.SetValue(true); - EXPECT_TRUE(boolean.GetValue()); - EXPECT_TRUE(prefs.GetBoolean(kBoolPref)); - EXPECT_TRUE(*boolean); - - // Try changing back through the pref. - prefs.SetBoolean(kBoolPref, false); - EXPECT_FALSE(prefs.GetBoolean(kBoolPref)); - EXPECT_FALSE(boolean.GetValue()); - EXPECT_FALSE(*boolean); - - // Test int - IntegerPrefMember integer; - integer.Init(kIntPref, &prefs, NULL); - - // Check the defaults - EXPECT_EQ(0, prefs.GetInteger(kIntPref)); - EXPECT_EQ(0, integer.GetValue()); - EXPECT_EQ(0, *integer); - - // Try changing through the member variable. - integer.SetValue(5); - EXPECT_EQ(5, integer.GetValue()); - EXPECT_EQ(5, prefs.GetInteger(kIntPref)); - EXPECT_EQ(5, *integer); - - // Try changing back through the pref. - prefs.SetInteger(kIntPref, 2); - EXPECT_EQ(2, prefs.GetInteger(kIntPref)); - EXPECT_EQ(2, integer.GetValue()); - EXPECT_EQ(2, *integer); - - // Test real (double) - RealPrefMember real; - real.Init(kRealPref, &prefs, NULL); - - // Check the defaults - EXPECT_EQ(0.0, prefs.GetReal(kRealPref)); - EXPECT_EQ(0.0, real.GetValue()); - EXPECT_EQ(0.0, *real); - - // Try changing through the member variable. - real.SetValue(1.0); - EXPECT_EQ(1.0, real.GetValue()); - EXPECT_EQ(1.0, prefs.GetReal(kRealPref)); - EXPECT_EQ(1.0, *real); - - // Try changing back through the pref. - prefs.SetReal(kRealPref, 3.0); - EXPECT_EQ(3.0, prefs.GetReal(kRealPref)); - EXPECT_EQ(3.0, real.GetValue()); - EXPECT_EQ(3.0, *real); - - // Test string - StringPrefMember string; - string.Init(kStringPref, &prefs, NULL); - - // Check the defaults - EXPECT_EQ(L"default", prefs.GetString(kStringPref)); - EXPECT_EQ(L"default", string.GetValue()); - EXPECT_EQ(L"default", *string); - - // Try changing through the member variable. - string.SetValue(L"foo"); - EXPECT_EQ(L"foo", string.GetValue()); - EXPECT_EQ(L"foo", prefs.GetString(kStringPref)); - EXPECT_EQ(L"foo", *string); - - // Try changing back through the pref. - prefs.SetString(kStringPref, L"bar"); - EXPECT_EQ(L"bar", prefs.GetString(kStringPref)); - EXPECT_EQ(L"bar", string.GetValue()); - EXPECT_EQ(L"bar", *string); -} - -TEST(PrefMemberTest, TwoPrefs) { - // Make sure two RealPrefMembers stay in sync. - PrefService prefs((FilePath())); - RegisterTestPrefs(&prefs); - - RealPrefMember pref1; - pref1.Init(kRealPref, &prefs, NULL); - RealPrefMember pref2; - pref2.Init(kRealPref, &prefs, NULL); - - pref1.SetValue(2.3); - EXPECT_EQ(2.3, *pref2); - - pref2.SetValue(3.5); - EXPECT_EQ(3.5, *pref1); - - prefs.SetReal(kRealPref, 4.2); - EXPECT_EQ(4.2, *pref1); - EXPECT_EQ(4.2, *pref2); -} - -TEST(PrefMemberTest, Observer) { - PrefService prefs((FilePath())); - RegisterTestPrefs(&prefs); - - PrefMemberTestClass test_obj(&prefs); - EXPECT_EQ(L"default", *test_obj.str_); - - // Calling SetValue should not fire the observer. - test_obj.str_.SetValue(L"hello"); - EXPECT_EQ(0, test_obj.observe_cnt_); - EXPECT_EQ(L"hello", prefs.GetString(kStringPref)); - - // Changing the pref does fire the observer. - prefs.SetString(kStringPref, L"world"); - EXPECT_EQ(1, test_obj.observe_cnt_); - EXPECT_EQ(L"world", *(test_obj.str_)); - - // Not changing the value should not fire the observer. - prefs.SetString(kStringPref, L"world"); - EXPECT_EQ(1, test_obj.observe_cnt_); - EXPECT_EQ(L"world", *(test_obj.str_)); - - prefs.SetString(kStringPref, L"hello"); - EXPECT_EQ(2, test_obj.observe_cnt_); - EXPECT_EQ(L"hello", prefs.GetString(kStringPref)); -} - -TEST(PrefMemberTest, NoInit) { - // Make sure not calling Init on a PrefMember doesn't cause problems. - IntegerPrefMember pref; -} diff --git a/chrome/common/pref_service.cc b/chrome/common/pref_service.cc deleted file mode 100644 index 25710b2..0000000 --- a/chrome/common/pref_service.cc +++ /dev/null @@ -1,684 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/common/pref_service.h" - -#include "app/l10n_util.h" -#include "base/logging.h" -#include "base/message_loop.h" -#include "base/stl_util-inl.h" -#include "base/string_util.h" -#include "base/sys_string_conversions.h" -#include "build/build_config.h" -#include "chrome/common/json_value_serializer.h" -#include "chrome/common/notification_service.h" -#include "grit/generated_resources.h" - -namespace { - -// A helper function for RegisterLocalized*Pref that creates a Value* based on -// the string value in the locale dll. Because we control the values in a -// locale dll, this should always return a Value of the appropriate type. -Value* CreateLocaleDefaultValue(Value::ValueType type, int message_id) { - std::wstring resource_string = l10n_util::GetString(message_id); - DCHECK(!resource_string.empty()); - switch (type) { - case Value::TYPE_BOOLEAN: { - if (L"true" == resource_string) - return Value::CreateBooleanValue(true); - if (L"false" == resource_string) - return Value::CreateBooleanValue(false); - break; - } - - case Value::TYPE_INTEGER: { - return Value::CreateIntegerValue( - StringToInt(WideToUTF16Hack(resource_string))); - break; - } - - case Value::TYPE_REAL: { - return Value::CreateRealValue( - StringToDouble(WideToUTF16Hack(resource_string))); - break; - } - - case Value::TYPE_STRING: { - return Value::CreateStringValue(resource_string); - break; - } - - default: { - NOTREACHED() << - "list and dictionary types can not have default locale values"; - } - } - NOTREACHED(); - return Value::CreateNullValue(); -} - -} // namespace - -PrefService::PrefService(const FilePath& pref_filename) - : persistent_(new DictionaryValue), - writer_(pref_filename) { - ReloadPersistentPrefs(); -} - -PrefService::~PrefService() { - DCHECK(CalledOnValidThread()); - - // Verify that there are no pref observers when we shut down. - for (PrefObserverMap::iterator it = pref_observers_.begin(); - it != pref_observers_.end(); ++it) { - NotificationObserverList::Iterator obs_iterator(*(it->second)); - if (obs_iterator.GetNext()) { - LOG(WARNING) << "pref observer found at shutdown " << it->first; - } - } - - STLDeleteContainerPointers(prefs_.begin(), prefs_.end()); - prefs_.clear(); - STLDeleteContainerPairSecondPointers(pref_observers_.begin(), - pref_observers_.end()); - pref_observers_.clear(); - - if (writer_.HasPendingWrite()) - writer_.DoScheduledWrite(); -} - -bool PrefService::ReloadPersistentPrefs() { - DCHECK(CalledOnValidThread()); - - JSONFileValueSerializer serializer(writer_.path()); - scoped_ptr<Value> root(serializer.Deserialize(NULL)); - if (!root.get()) - return false; - - // Preferences should always have a dictionary root. - if (!root->IsType(Value::TYPE_DICTIONARY)) - return false; - - persistent_.reset(static_cast<DictionaryValue*>(root.release())); - for (PreferenceSet::iterator it = prefs_.begin(); - it != prefs_.end(); ++it) { - (*it)->root_pref_ = persistent_.get(); - } - - return true; -} - -bool PrefService::SavePersistentPrefs() { - DCHECK(CalledOnValidThread()); - - std::string data; - if (!SerializeData(&data)) - return false; - - writer_.WriteNow(data); - return true; -} - -void PrefService::ScheduleSavePersistentPrefs() { - DCHECK(CalledOnValidThread()); - writer_.ScheduleWrite(this); -} - -void PrefService::RegisterBooleanPref(const wchar_t* path, - bool default_value) { - Preference* pref = new Preference(persistent_.get(), path, - Value::CreateBooleanValue(default_value)); - RegisterPreference(pref); -} - -void PrefService::RegisterIntegerPref(const wchar_t* path, - int default_value) { - Preference* pref = new Preference(persistent_.get(), path, - Value::CreateIntegerValue(default_value)); - RegisterPreference(pref); -} - -void PrefService::RegisterRealPref(const wchar_t* path, - double default_value) { - Preference* pref = new Preference(persistent_.get(), path, - Value::CreateRealValue(default_value)); - RegisterPreference(pref); -} - -void PrefService::RegisterStringPref(const wchar_t* path, - const std::wstring& default_value) { - Preference* pref = new Preference(persistent_.get(), path, - Value::CreateStringValue(default_value)); - RegisterPreference(pref); -} - -void PrefService::RegisterFilePathPref(const wchar_t* path, - const FilePath& default_value) { - Preference* pref = new Preference(persistent_.get(), path, - Value::CreateStringValue(default_value.value())); - RegisterPreference(pref); -} - -void PrefService::RegisterListPref(const wchar_t* path) { - Preference* pref = new Preference(persistent_.get(), path, - new ListValue); - RegisterPreference(pref); -} - -void PrefService::RegisterDictionaryPref(const wchar_t* path) { - Preference* pref = new Preference(persistent_.get(), path, - new DictionaryValue()); - RegisterPreference(pref); -} - -void PrefService::RegisterLocalizedBooleanPref(const wchar_t* path, - int locale_default_message_id) { - Preference* pref = new Preference(persistent_.get(), path, - CreateLocaleDefaultValue(Value::TYPE_BOOLEAN, locale_default_message_id)); - RegisterPreference(pref); -} - -void PrefService::RegisterLocalizedIntegerPref(const wchar_t* path, - int locale_default_message_id) { - Preference* pref = new Preference(persistent_.get(), path, - CreateLocaleDefaultValue(Value::TYPE_INTEGER, locale_default_message_id)); - RegisterPreference(pref); -} - -void PrefService::RegisterLocalizedRealPref(const wchar_t* path, - int locale_default_message_id) { - Preference* pref = new Preference(persistent_.get(), path, - CreateLocaleDefaultValue(Value::TYPE_REAL, locale_default_message_id)); - RegisterPreference(pref); -} - -void PrefService::RegisterLocalizedStringPref(const wchar_t* path, - int locale_default_message_id) { - Preference* pref = new Preference(persistent_.get(), path, - CreateLocaleDefaultValue(Value::TYPE_STRING, locale_default_message_id)); - RegisterPreference(pref); -} - -bool PrefService::GetBoolean(const wchar_t* path) const { - DCHECK(CalledOnValidThread()); - - bool result = false; - - const Preference* pref = FindPreference(path); - if (!pref) { - NOTREACHED() << "Trying to read an unregistered pref: " << path; - return result; - } - bool rv = pref->GetValue()->GetAsBoolean(&result); - DCHECK(rv); - return result; -} - -int PrefService::GetInteger(const wchar_t* path) const { - DCHECK(CalledOnValidThread()); - - int result = 0; - - const Preference* pref = FindPreference(path); - if (!pref) { - NOTREACHED() << "Trying to read an unregistered pref: " << path; - return result; - } - bool rv = pref->GetValue()->GetAsInteger(&result); - DCHECK(rv); - return result; -} - -double PrefService::GetReal(const wchar_t* path) const { - DCHECK(CalledOnValidThread()); - - double result = 0.0; - - const Preference* pref = FindPreference(path); - if (!pref) { - NOTREACHED() << "Trying to read an unregistered pref: " << path; - return result; - } - bool rv = pref->GetValue()->GetAsReal(&result); - DCHECK(rv); - return result; -} - -std::wstring PrefService::GetString(const wchar_t* path) const { - DCHECK(CalledOnValidThread()); - - std::wstring result; - - const Preference* pref = FindPreference(path); - if (!pref) { - NOTREACHED() << "Trying to read an unregistered pref: " << path; - return result; - } - bool rv = pref->GetValue()->GetAsString(&result); - DCHECK(rv); - return result; -} - -FilePath PrefService::GetFilePath(const wchar_t* path) const { - DCHECK(CalledOnValidThread()); - - FilePath::StringType result; - - const Preference* pref = FindPreference(path); - if (!pref) { - NOTREACHED() << "Trying to read an unregistered pref: " << path; - return FilePath(result); - } - bool rv = pref->GetValue()->GetAsString(&result); - DCHECK(rv); -#if defined(OS_POSIX) - // We store filepaths as UTF8, so convert it back to the system type. - result = base::SysWideToNativeMB(UTF8ToWide(result)); -#endif - return FilePath(result); -} - -bool PrefService::HasPrefPath(const wchar_t* path) const { - Value* value = NULL; - return persistent_->Get(path, &value); -} - -const PrefService::Preference* PrefService::FindPreference( - const wchar_t* pref_name) const { - DCHECK(CalledOnValidThread()); - Preference p(NULL, pref_name, NULL); - PreferenceSet::const_iterator it = prefs_.find(&p); - return it == prefs_.end() ? NULL : *it; -} - -const DictionaryValue* PrefService::GetDictionary(const wchar_t* path) const { - DCHECK(CalledOnValidThread()); - - const Preference* pref = FindPreference(path); - if (!pref) { - NOTREACHED() << "Trying to read an unregistered pref: " << path; - return NULL; - } - const Value* value = pref->GetValue(); - if (value->GetType() == Value::TYPE_NULL) - return NULL; - return static_cast<const DictionaryValue*>(value); -} - -const ListValue* PrefService::GetList(const wchar_t* path) const { - DCHECK(CalledOnValidThread()); - - const Preference* pref = FindPreference(path); - if (!pref) { - NOTREACHED() << "Trying to read an unregistered pref: " << path; - return NULL; - } - const Value* value = pref->GetValue(); - if (value->GetType() == Value::TYPE_NULL) - return NULL; - return static_cast<const ListValue*>(value); -} - -void PrefService::AddPrefObserver(const wchar_t* path, - NotificationObserver* obs) { - DCHECK(CalledOnValidThread()); - - const Preference* pref = FindPreference(path); - if (!pref) { - NOTREACHED() << "Trying to add an observer for an unregistered pref: " - << path; - return; - } - - // Get the pref observer list associated with the path. - NotificationObserverList* observer_list = NULL; - PrefObserverMap::iterator observer_iterator = pref_observers_.find(path); - if (observer_iterator == pref_observers_.end()) { - observer_list = new NotificationObserverList; - pref_observers_[path] = observer_list; - } else { - observer_list = observer_iterator->second; - } - - // Verify that this observer doesn't already exist. - NotificationObserverList::Iterator it(*observer_list); - NotificationObserver* existing_obs; - while ((existing_obs = it.GetNext()) != NULL) { - DCHECK(existing_obs != obs) << path << " observer already registered"; - if (existing_obs == obs) - return; - } - - // Ok, safe to add the pref observer. - observer_list->AddObserver(obs); -} - -void PrefService::RemovePrefObserver(const wchar_t* path, - NotificationObserver* obs) { - DCHECK(CalledOnValidThread()); - - PrefObserverMap::iterator observer_iterator = pref_observers_.find(path); - if (observer_iterator == pref_observers_.end()) { - return; - } - - NotificationObserverList* observer_list = observer_iterator->second; - observer_list->RemoveObserver(obs); -} - -void PrefService::RegisterPreference(Preference* pref) { - DCHECK(CalledOnValidThread()); - - if (FindPreference(pref->name().c_str())) { - NOTREACHED() << "Tried to register duplicate pref " << pref->name(); - delete pref; - return; - } - prefs_.insert(pref); -} - -void PrefService::ClearPref(const wchar_t* path) { - DCHECK(CalledOnValidThread()); - - const Preference* pref = FindPreference(path); - if (!pref) { - NOTREACHED() << "Trying to clear an unregistered pref: " << path; - return; - } - - Value* value; - bool has_old_value = persistent_->Get(path, &value); - persistent_->Remove(path, NULL); - - if (has_old_value) - FireObservers(path); -} - -void PrefService::Set(const wchar_t* path, const Value& value) { - DCHECK(CalledOnValidThread()); - - const Preference* pref = FindPreference(path); - if (!pref) { - NOTREACHED() << "Trying to write an unregistered pref: " << path; - return; - } - if (pref->type() != value.GetType()) { - NOTREACHED() << "Wrong type for Set: " << path; - } - - scoped_ptr<Value> old_value(GetPrefCopy(path)); - persistent_->Set(path, value.DeepCopy()); - - FireObserversIfChanged(path, old_value.get()); -} - -void PrefService::SetBoolean(const wchar_t* path, bool value) { - DCHECK(CalledOnValidThread()); - - const Preference* pref = FindPreference(path); - if (!pref) { - NOTREACHED() << "Trying to write an unregistered pref: " << path; - return; - } - if (pref->type() != Value::TYPE_BOOLEAN) { - NOTREACHED() << "Wrong type for SetBoolean: " << path; - return; - } - - scoped_ptr<Value> old_value(GetPrefCopy(path)); - persistent_->SetBoolean(path, value); - - FireObserversIfChanged(path, old_value.get()); -} - -void PrefService::SetInteger(const wchar_t* path, int value) { - DCHECK(CalledOnValidThread()); - - const Preference* pref = FindPreference(path); - if (!pref) { - NOTREACHED() << "Trying to write an unregistered pref: " << path; - return; - } - if (pref->type() != Value::TYPE_INTEGER) { - NOTREACHED() << "Wrong type for SetInteger: " << path; - return; - } - - scoped_ptr<Value> old_value(GetPrefCopy(path)); - persistent_->SetInteger(path, value); - - FireObserversIfChanged(path, old_value.get()); -} - -void PrefService::SetReal(const wchar_t* path, double value) { - DCHECK(CalledOnValidThread()); - - const Preference* pref = FindPreference(path); - if (!pref) { - NOTREACHED() << "Trying to write an unregistered pref: " << path; - return; - } - if (pref->type() != Value::TYPE_REAL) { - NOTREACHED() << "Wrong type for SetReal: " << path; - return; - } - - scoped_ptr<Value> old_value(GetPrefCopy(path)); - persistent_->SetReal(path, value); - - FireObserversIfChanged(path, old_value.get()); -} - -void PrefService::SetString(const wchar_t* path, const std::wstring& value) { - DCHECK(CalledOnValidThread()); - - const Preference* pref = FindPreference(path); - if (!pref) { - NOTREACHED() << "Trying to write an unregistered pref: " << path; - return; - } - if (pref->type() != Value::TYPE_STRING) { - NOTREACHED() << "Wrong type for SetString: " << path; - return; - } - - scoped_ptr<Value> old_value(GetPrefCopy(path)); - persistent_->SetString(path, value); - - FireObserversIfChanged(path, old_value.get()); -} - -void PrefService::SetFilePath(const wchar_t* path, const FilePath& value) { - DCHECK(CalledOnValidThread()); - - const Preference* pref = FindPreference(path); - if (!pref) { - NOTREACHED() << "Trying to write an unregistered pref: " << path; - return; - } - if (pref->type() != Value::TYPE_STRING) { - NOTREACHED() << "Wrong type for SetFilePath: " << path; - return; - } - - scoped_ptr<Value> old_value(GetPrefCopy(path)); -#if defined(OS_POSIX) - // Value::SetString only knows about UTF8 strings, so convert the path from - // the system native value to UTF8. - std::string path_utf8 = WideToUTF8(base::SysNativeMBToWide(value.value())); - persistent_->SetString(path, path_utf8); -#else - persistent_->SetString(path, value.value()); -#endif - - FireObserversIfChanged(path, old_value.get()); -} - -void PrefService::SetInt64(const wchar_t* path, int64 value) { - DCHECK(CalledOnValidThread()); - - const Preference* pref = FindPreference(path); - if (!pref) { - NOTREACHED() << "Trying to write an unregistered pref: " << path; - return; - } - if (pref->type() != Value::TYPE_STRING) { - NOTREACHED() << "Wrong type for SetInt64: " << path; - return; - } - - scoped_ptr<Value> old_value(GetPrefCopy(path)); - persistent_->SetString(path, Int64ToWString(value)); - - FireObserversIfChanged(path, old_value.get()); -} - -int64 PrefService::GetInt64(const wchar_t* path) const { - DCHECK(CalledOnValidThread()); - - const Preference* pref = FindPreference(path); - if (!pref) { - NOTREACHED() << "Trying to read an unregistered pref: " << path; - return 0; - } - std::wstring result(L"0"); - bool rv = pref->GetValue()->GetAsString(&result); - DCHECK(rv); - return StringToInt64(WideToUTF16Hack(result)); -} - -void PrefService::RegisterInt64Pref(const wchar_t* path, int64 default_value) { - Preference* pref = new Preference(persistent_.get(), path, - Value::CreateStringValue(Int64ToWString(default_value))); - RegisterPreference(pref); -} - -DictionaryValue* PrefService::GetMutableDictionary(const wchar_t* path) { - DCHECK(CalledOnValidThread()); - - const Preference* pref = FindPreference(path); - if (!pref) { - NOTREACHED() << "Trying to get an unregistered pref: " << path; - return NULL; - } - if (pref->type() != Value::TYPE_DICTIONARY) { - NOTREACHED() << "Wrong type for GetMutableDictionary: " << path; - return NULL; - } - - DictionaryValue* dict = NULL; - if (!persistent_->GetDictionary(path, &dict)) { - dict = new DictionaryValue; - persistent_->Set(path, dict); - } - return dict; -} - -ListValue* PrefService::GetMutableList(const wchar_t* path) { - DCHECK(CalledOnValidThread()); - - const Preference* pref = FindPreference(path); - if (!pref) { - NOTREACHED() << "Trying to get an unregistered pref: " << path; - return NULL; - } - if (pref->type() != Value::TYPE_LIST) { - NOTREACHED() << "Wrong type for GetMutableList: " << path; - return NULL; - } - - ListValue* list = NULL; - if (!persistent_->GetList(path, &list)) { - list = new ListValue; - persistent_->Set(path, list); - } - return list; -} - -Value* PrefService::GetPrefCopy(const wchar_t* path) { - DCHECK(CalledOnValidThread()); - - const Preference* pref = FindPreference(path); - DCHECK(pref); - return pref->GetValue()->DeepCopy(); -} - -void PrefService::FireObserversIfChanged(const wchar_t* path, - const Value* old_value) { - Value* new_value = NULL; - persistent_->Get(path, &new_value); - if (!old_value->Equals(new_value)) - FireObservers(path); -} - -void PrefService::FireObservers(const wchar_t* path) { - DCHECK(CalledOnValidThread()); - - // Convert path to a std::wstring because the Details constructor requires a - // class. - std::wstring path_str(path); - PrefObserverMap::iterator observer_iterator = pref_observers_.find(path_str); - if (observer_iterator == pref_observers_.end()) - return; - - NotificationObserverList::Iterator it(*(observer_iterator->second)); - NotificationObserver* observer; - while ((observer = it.GetNext()) != NULL) { - observer->Observe(NotificationType::PREF_CHANGED, - Source<PrefService>(this), - Details<std::wstring>(&path_str)); - } -} - -bool PrefService::SerializeData(std::string* output) { - // TODO(tc): Do we want to prune webkit preferences that match the default - // value? - JSONStringValueSerializer serializer(output); - serializer.set_pretty_print(true); - scoped_ptr<DictionaryValue> copy(persistent_->DeepCopyWithoutEmptyChildren()); - return serializer.Serialize(*(copy.get())); -} - -/////////////////////////////////////////////////////////////////////////////// -// PrefService::Preference - -PrefService::Preference::Preference(DictionaryValue* root_pref, - const wchar_t* name, - Value* default_value) - : type_(Value::TYPE_NULL), - name_(name), - default_value_(default_value), - root_pref_(root_pref) { - DCHECK(name); - - if (default_value) { - type_ = default_value->GetType(); - DCHECK(type_ != Value::TYPE_NULL && type_ != Value::TYPE_BINARY) << - "invalid preference type: " << type_; - } - - // We set the default value of lists and dictionaries to be null so it's - // easier for callers to check for empty list/dict prefs. - if (Value::TYPE_LIST == type_ || Value::TYPE_DICTIONARY == type_) - default_value_.reset(Value::CreateNullValue()); -} - -const Value* PrefService::Preference::GetValue() const { - DCHECK(NULL != root_pref_) << - "Must register pref before getting its value"; - - Value* temp_value = NULL; - if (root_pref_->Get(name_.c_str(), &temp_value) && - temp_value->GetType() == type_) { - return temp_value; - } - - // Pref not found, just return the app default. - return default_value_.get(); -} - -bool PrefService::Preference::IsDefaultValue() const { - DCHECK(default_value_.get()); - return default_value_->Equals(GetValue()); -} diff --git a/chrome/common/pref_service.h b/chrome/common/pref_service.h deleted file mode 100644 index 9d9b6d2..0000000 --- a/chrome/common/pref_service.h +++ /dev/null @@ -1,222 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This provides a way to access the application's current preferences. -// This service has two preference stores, one for "persistent" preferences, -// which get serialized for use in the next session, and one for "transient" -// preferences, which are in effect for only the current session -// (this usually encodes things like command-line switches). -// -// Calling the getter functions in this class basically looks at both the -// persistent and transient stores, where any corresponding value in the -// transient store overrides the one in the persistent store. - -#ifndef CHROME_COMMON_PREF_SERVICE_H_ -#define CHROME_COMMON_PREF_SERVICE_H_ - -#include <set> - -#include "base/file_path.h" -#include "base/hash_tables.h" -#include "base/non_thread_safe.h" -#include "base/observer_list.h" -#include "base/scoped_ptr.h" -#include "base/values.h" -#include "chrome/common/important_file_writer.h" - -class NotificationObserver; -class Preference; - -class PrefService : public NonThreadSafe, - public ImportantFileWriter::DataSerializer { - public: - - // A helper class to store all the information associated with a preference. - class Preference { - public: - - // The type of the preference is determined by the type of |default_value|. - // Therefore, the type needs to be a boolean, integer, real, string, - // dictionary (a branch), or list. You shouldn't need to construct this on - // your own, use the PrefService::Register*Pref methods instead. - // |default_value| will be owned by the Preference object. - Preference(DictionaryValue* root_pref, - const wchar_t* name, - Value* default_value); - ~Preference() {} - - Value::ValueType type() const { return type_; } - - // Returns the name of the Preference (i.e., the key, e.g., - // browser.window_placement). - const std::wstring name() const { return name_; } - - // Returns the value of the Preference. If there is no user specified - // value, it returns the default value. - const Value* GetValue() const; - - // Returns true if the current value matches the default value. - bool IsDefaultValue() const; - - private: - friend class PrefService; - - Value::ValueType type_; - std::wstring name_; - scoped_ptr<Value> default_value_; - - // A reference to the pref service's persistent prefs. - DictionaryValue* root_pref_; - - DISALLOW_COPY_AND_ASSIGN(Preference); - }; - - // |pref_filename| is the path to the prefs file we will try to load or save - // to. Saves will be executed on the file thread. - explicit PrefService(const FilePath& pref_filename); - ~PrefService(); - - // Reloads the data from file. This should only be called when the importer - // is running during first run, and the main process may not change pref - // values while the importer process is running. Returns true on success. - bool ReloadPersistentPrefs(); - - // Writes the data to disk. The return value only reflects whether - // serialization was successful; we don't know whether the data actually made - // it on disk (since it's on a different thread). This should only be used if - // we need to save immediately (basically, during shutdown). Otherwise, you - // should use ScheduleSavePersistentPrefs. - bool SavePersistentPrefs(); - - // Serializes the data and schedules save using ImportantFileWriter. - void ScheduleSavePersistentPrefs(); - - // Make the PrefService aware of a pref. - void RegisterBooleanPref(const wchar_t* path, - bool default_value); - void RegisterIntegerPref(const wchar_t* path, - int default_value); - void RegisterRealPref(const wchar_t* path, - double default_value); - void RegisterStringPref(const wchar_t* path, - const std::wstring& default_value); - void RegisterFilePathPref(const wchar_t* path, - const FilePath& default_value); - void RegisterListPref(const wchar_t* path); - void RegisterDictionaryPref(const wchar_t* path); - - // These varients use a default value from the locale dll instead. - void RegisterLocalizedBooleanPref(const wchar_t* path, - int locale_default_message_id); - void RegisterLocalizedIntegerPref(const wchar_t* path, - int locale_default_message_id); - void RegisterLocalizedRealPref(const wchar_t* path, - int locale_default_message_id); - void RegisterLocalizedStringPref(const wchar_t* path, - int locale_default_message_id); - - // If the path is valid and the value at the end of the path matches the type - // specified, it will return the specified value. Otherwise, the default - // value (set when the pref was registered) will be returned. - bool GetBoolean(const wchar_t* path) const; - int GetInteger(const wchar_t* path) const; - double GetReal(const wchar_t* path) const; - std::wstring GetString(const wchar_t* path) const; - FilePath GetFilePath(const wchar_t* path) const; - - // Returns the branch if it exists. If it's not a branch or the branch does - // not exist, returns NULL. - const DictionaryValue* GetDictionary(const wchar_t* path) const; - const ListValue* GetList(const wchar_t* path) const; - - // If the pref at the given path changes, we call the observer's Observe - // method with NOTIFY_PREF_CHANGED. - void AddPrefObserver(const wchar_t* path, NotificationObserver* obs); - void RemovePrefObserver(const wchar_t* path, NotificationObserver* obs); - - // Removes a user pref and restores the pref to its default value. - void ClearPref(const wchar_t* path); - - // If the path is valid (i.e., registered), update the pref value. - void Set(const wchar_t* path, const Value& value); - void SetBoolean(const wchar_t* path, bool value); - void SetInteger(const wchar_t* path, int value); - void SetReal(const wchar_t* path, double value); - void SetString(const wchar_t* path, const std::wstring& value); - void SetFilePath(const wchar_t* path, const FilePath& value); - - // Int64 helper methods that actually store the given value as a string. - // Note that if obtaining the named value via GetDictionary or GetList, the - // Value type will be TYPE_STRING. - void SetInt64(const wchar_t* path, int64 value); - int64 GetInt64(const wchar_t* path) const; - void RegisterInt64Pref(const wchar_t* path, int64 default_value); - - // Used to set the value of dictionary or list values in the pref tree. This - // will create a dictionary or list if one does not exist in the pref tree. - // This method returns NULL only if you're requesting an unregistered pref or - // a non-dict/non-list pref. - // WARNING: Changes to the dictionary or list will not automatically notify - // pref observers. TODO(tc): come up with a way to still fire observers. - DictionaryValue* GetMutableDictionary(const wchar_t* path); - ListValue* GetMutableList(const wchar_t* path); - - // Returns true if a value has been set for the specified path. - // NOTE: this is NOT the same as FindPreference. In particular - // FindPreference returns whether RegisterXXX has been invoked, where as - // this checks if a value exists for the path. - bool HasPrefPath(const wchar_t* path) const; - - class PreferencePathComparator { - public: - bool operator() (Preference* lhs, Preference* rhs) const { - return lhs->name() < rhs->name(); - } - }; - typedef std::set<Preference*, PreferencePathComparator> PreferenceSet; - const PreferenceSet& preference_set() const { return prefs_; } - - // A helper method to quickly look up a preference. Returns NULL if the - // preference is not registered. - const Preference* FindPreference(const wchar_t* pref_name) const; - - // ImportantFileWriter::DataSerializer - virtual bool SerializeData(std::string* output); - - private: - // Add a preference to the PreferenceMap. If the pref already exists, return - // false. This method takes ownership of |pref|. - void RegisterPreference(Preference* pref); - - // Returns a copy of the current pref value. The caller is responsible for - // deleting the returned object. - Value* GetPrefCopy(const wchar_t* pref_name); - - // For the given pref_name, fire any observer of the pref. - void FireObservers(const wchar_t* pref_name); - - // For the given pref_name, fire any observer of the pref only if |old_value| - // is different from the current value. - void FireObserversIfChanged(const wchar_t* pref_name, - const Value* old_value); - - scoped_ptr<DictionaryValue> persistent_; - - // Helper for safe writing pref data. - ImportantFileWriter writer_; - - // A set of all the registered Preference objects. - PreferenceSet prefs_; - - // A map from pref names to a list of observers. Observers get fired in the - // order they are added. - typedef ObserverList<NotificationObserver> NotificationObserverList; - typedef base::hash_map<std::wstring, NotificationObserverList*> - PrefObserverMap; - PrefObserverMap pref_observers_; - - DISALLOW_COPY_AND_ASSIGN(PrefService); -}; - -#endif // CHROME_COMMON_PREF_SERVICE_H_ diff --git a/chrome/common/pref_service_uitest.cc b/chrome/common/pref_service_uitest.cc deleted file mode 100644 index 04430b5..0000000 --- a/chrome/common/pref_service_uitest.cc +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <string> - -#include "base/command_line.h" -#include "base/file_util.h" -#include "base/gfx/rect.h" -#include "base/test/test_file_util.h" -#include "base/values.h" -#include "build/build_config.h" -#include "chrome/common/chrome_constants.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/common/json_value_serializer.h" -#include "chrome/common/pref_names.h" -#include "chrome/test/automation/browser_proxy.h" -#include "chrome/test/automation/window_proxy.h" -#include "chrome/test/ui/ui_test.h" - -class PreferenceServiceTest : public UITest { -public: - void SetUp() { - PathService::Get(base::DIR_TEMP, &tmp_profile_); - tmp_profile_ = tmp_profile_.AppendASCII("tmp_profile"); - - // Create a fresh, empty copy of this directory. - file_util::Delete(tmp_profile_, true); - file_util::CreateDirectory(tmp_profile_); - - FilePath reference_pref_file = - test_data_directory_ - .AppendASCII("profiles") - .AppendASCII("window_placement") - .Append(chrome::kLocalStateFilename); - - tmp_pref_file_ = tmp_profile_.Append(chrome::kLocalStateFilename); - - ASSERT_TRUE(file_util::PathExists(reference_pref_file)); - - // Copy only the Local State file, the rest will be automatically created - ASSERT_TRUE(file_util::CopyFile(reference_pref_file, tmp_pref_file_)); - -#if defined(OS_WIN) - // Make the copy writable. On POSIX we assume the umask allows files - // we create to be writable. - ASSERT_TRUE(::SetFileAttributesW(tmp_pref_file_.value().c_str(), - FILE_ATTRIBUTE_NORMAL)); -#endif - - launch_arguments_.AppendSwitchWithValue(switches::kUserDataDir, - tmp_profile_.ToWStringHack()); - } - - bool LaunchAppWithProfile() { - if (!file_util::PathExists(tmp_pref_file_)) - return false; - UITest::SetUp(); - return true; - } - - void TearDown() { - UITest::TearDown(); - - EXPECT_TRUE(file_util::DieFileDie(tmp_profile_, true)); - } - -public: - FilePath tmp_pref_file_; - FilePath tmp_profile_; -}; - -#if defined(OS_WIN) -// This test verifies that the window position from the prefs file is restored -// when the app restores. This doesn't really make sense on Linux, where -// the window manager might fight with you over positioning. However, we -// might be able to make this work on buildbots. -// Also, not sure what should happen on the mac. In any case, the code below -// (minus the Windows bits) compiles fine on my Linux box now. -// TODO(port): revisit this. -TEST_F(PreferenceServiceTest, PreservedWindowPlacementIsLoaded) { - // The window should open with the reference profile - ASSERT_TRUE(LaunchAppWithProfile()); - - ASSERT_TRUE(file_util::PathExists(tmp_pref_file_)); - - JSONFileValueSerializer deserializer(tmp_pref_file_); - scoped_ptr<Value> root(deserializer.Deserialize(NULL)); - - ASSERT_TRUE(root.get()); - ASSERT_TRUE(root->IsType(Value::TYPE_DICTIONARY)); - - DictionaryValue* root_dict = static_cast<DictionaryValue*>(root.get()); - - // Retrieve the screen rect for the launched window - scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0)); - ASSERT_TRUE(browser.get()); - scoped_refptr<WindowProxy> window(browser->GetWindow()); - - gfx::Rect bounds; - ASSERT_TRUE(window->GetBounds(&bounds)); - - // Retrieve the expected rect values from "Preferences" - int bottom = 0; - std::wstring kBrowserWindowPlacement(prefs::kBrowserWindowPlacement); - EXPECT_TRUE(root_dict->GetInteger(kBrowserWindowPlacement + L".bottom", - &bottom)); - EXPECT_EQ(bottom, bounds.y() + bounds.height()); - - int top = 0; - EXPECT_TRUE(root_dict->GetInteger(kBrowserWindowPlacement + L".top", - &top)); - EXPECT_EQ(top, bounds.y()); - - int left = 0; - EXPECT_TRUE(root_dict->GetInteger(kBrowserWindowPlacement + L".left", - &left)); - EXPECT_EQ(left, bounds.x()); - - int right = 0; - EXPECT_TRUE(root_dict->GetInteger(kBrowserWindowPlacement + L".right", - &right)); - EXPECT_EQ(right, bounds.x() + bounds.width()); - - // Find if launched window is maximized. - bool is_window_maximized = false; - ASSERT_TRUE(window->IsMaximized(&is_window_maximized)); - bool is_maximized = false; - EXPECT_TRUE(root_dict->GetBoolean(kBrowserWindowPlacement + L".maximized", - &is_maximized)); - EXPECT_EQ(is_maximized, is_window_maximized); -} -#endif diff --git a/chrome/common/pref_service_unittest.cc b/chrome/common/pref_service_unittest.cc deleted file mode 100644 index c60b38b..0000000 --- a/chrome/common/pref_service_unittest.cc +++ /dev/null @@ -1,270 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "app/test/data/resource.h" -#include "base/file_util.h" -#include "base/message_loop.h" -#include "base/path_service.h" -#include "chrome/browser/chrome_thread.h" -#include "chrome/common/chrome_paths.h" -#include "chrome/common/json_value_serializer.h" -#include "chrome/common/notification_service.h" -#include "chrome/common/notification_type.h" -#include "chrome/common/pref_names.h" -#include "chrome/common/pref_service.h" -#include "testing/gtest/include/gtest/gtest.h" - -class PrefServiceTest : public testing::Test { - protected: - virtual void SetUp() { - // Name a subdirectory of the temp directory. - ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &test_dir_)); - test_dir_ = test_dir_.AppendASCII("PrefServiceTest"); - - // Create a fresh, empty copy of this directory. - file_util::Delete(test_dir_, true); - file_util::CreateDirectory(test_dir_); - - ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &data_dir_)); - data_dir_ = data_dir_.AppendASCII("pref_service"); - ASSERT_TRUE(file_util::PathExists(data_dir_)); - } - virtual void TearDown() { - // Clean up test directory - ASSERT_TRUE(file_util::Delete(test_dir_, true)); - ASSERT_FALSE(file_util::PathExists(test_dir_)); - } - - // the path to temporary directory used to contain the test operations - FilePath test_dir_; - // the path to the directory where the test data is stored - FilePath data_dir_; -}; - -class TestPrefObserver : public NotificationObserver { - public: - TestPrefObserver(const PrefService* prefs, const std::wstring& pref_name, - const std::wstring& new_pref_value) - : observer_fired_(false), - prefs_(prefs), - pref_name_(pref_name), - new_pref_value_(new_pref_value) { - } - virtual ~TestPrefObserver() {} - - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - EXPECT_EQ(type.value, NotificationType::PREF_CHANGED); - PrefService* prefs_in = Source<PrefService>(source).ptr(); - EXPECT_EQ(prefs_in, prefs_); - std::wstring* pref_name_in = Details<std::wstring>(details).ptr(); - EXPECT_EQ(*pref_name_in, pref_name_); - EXPECT_EQ(new_pref_value_, prefs_in->GetString(L"homepage")); - observer_fired_ = true; - } - - bool observer_fired() { return observer_fired_; } - - void Reset(const std::wstring& new_pref_value) { - observer_fired_ = false; - new_pref_value_ = new_pref_value; - } - - private: - bool observer_fired_; - const PrefService* prefs_; - const std::wstring pref_name_; - std::wstring new_pref_value_; -}; - -TEST_F(PrefServiceTest, Basic) { - { - // Test that it fails on nonexistent file. - FilePath bogus_input_file = data_dir_.AppendASCII("read.txt"); - PrefService prefs(bogus_input_file); - EXPECT_FALSE(prefs.ReloadPersistentPrefs()); - } - - ASSERT_TRUE(file_util::CopyFile(data_dir_.AppendASCII("read.json"), - test_dir_.AppendASCII("write.json"))); - - // Test that the persistent value can be loaded. - FilePath input_file = test_dir_.AppendASCII("write.json"); - ASSERT_TRUE(file_util::PathExists(input_file)); - PrefService prefs(input_file); - ASSERT_TRUE(prefs.ReloadPersistentPrefs()); - - // Register test prefs. - const wchar_t kNewWindowsInTabs[] = L"tabs.new_windows_in_tabs"; - const wchar_t kMaxTabs[] = L"tabs.max_tabs"; - const wchar_t kLongIntPref[] = L"long_int.pref"; - prefs.RegisterStringPref(prefs::kHomePage, L""); - prefs.RegisterBooleanPref(kNewWindowsInTabs, false); - prefs.RegisterIntegerPref(kMaxTabs, 0); - prefs.RegisterStringPref(kLongIntPref, L"2147483648"); - - std::wstring microsoft(L"http://www.microsoft.com"); - std::wstring cnn(L"http://www.cnn.com"); - std::wstring homepage(L"http://www.example.com"); - - EXPECT_EQ(cnn, prefs.GetString(prefs::kHomePage)); - - const wchar_t kSomeDirectory[] = L"some_directory"; - FilePath some_path(FILE_PATH_LITERAL("/usr/sbin/")); - prefs.RegisterFilePathPref(kSomeDirectory, FilePath()); - - // Test reading some other data types from sub-dictionaries, and - // writing to the persistent store. - EXPECT_TRUE(prefs.GetBoolean(kNewWindowsInTabs)); - prefs.SetBoolean(kNewWindowsInTabs, false); - EXPECT_FALSE(prefs.GetBoolean(kNewWindowsInTabs)); - - EXPECT_EQ(20, prefs.GetInteger(kMaxTabs)); - prefs.SetInteger(kMaxTabs, 10); - EXPECT_EQ(10, prefs.GetInteger(kMaxTabs)); - - EXPECT_EQ(2147483648LL, prefs.GetInt64(kLongIntPref)); - prefs.SetInt64(kLongIntPref, 214748364842LL); - EXPECT_EQ(214748364842LL, prefs.GetInt64(kLongIntPref)); - - EXPECT_EQ(FilePath::StringType(FILE_PATH_LITERAL("/usr/local/")), - prefs.GetFilePath(kSomeDirectory).value()); - prefs.SetFilePath(kSomeDirectory, some_path); - EXPECT_EQ(some_path.value(), prefs.GetFilePath(kSomeDirectory).value()); - - // Serialize and compare to expected output. - // SavePersistentPrefs uses ImportantFileWriter which needs a file thread. - MessageLoop message_loop; - ChromeThread file_thread(ChromeThread::FILE, &message_loop); - FilePath output_file = test_dir_.AppendASCII("write.json"); - FilePath golden_output_file = data_dir_.AppendASCII("write.golden.json"); - ASSERT_TRUE(file_util::PathExists(golden_output_file)); - ASSERT_TRUE(prefs.SavePersistentPrefs()); - MessageLoop::current()->RunAllPending(); - EXPECT_TRUE(file_util::TextContentsEqual(golden_output_file, output_file)); - ASSERT_TRUE(file_util::Delete(output_file, false)); -} - -TEST_F(PrefServiceTest, Observers) { - FilePath input_file = data_dir_.AppendASCII("read.json"); - EXPECT_TRUE(file_util::PathExists(input_file)); - - PrefService prefs(input_file); - - EXPECT_TRUE(prefs.ReloadPersistentPrefs()); - - const wchar_t pref_name[] = L"homepage"; - prefs.RegisterStringPref(pref_name, L""); - EXPECT_EQ(std::wstring(L"http://www.cnn.com"), prefs.GetString(pref_name)); - - const std::wstring new_pref_value(L"http://www.google.com/"); - TestPrefObserver obs(&prefs, pref_name, new_pref_value); - prefs.AddPrefObserver(pref_name, &obs); - // This should fire the checks in TestPrefObserver::Observe. - prefs.SetString(pref_name, new_pref_value); - - // Make sure the tests were actually run. - EXPECT_TRUE(obs.observer_fired()); - - // Now try adding a second pref observer. - const std::wstring new_pref_value2(L"http://www.youtube.com/"); - obs.Reset(new_pref_value2); - TestPrefObserver obs2(&prefs, pref_name, new_pref_value2); - prefs.AddPrefObserver(pref_name, &obs2); - // This should fire the checks in obs and obs2. - prefs.SetString(pref_name, new_pref_value2); - EXPECT_TRUE(obs.observer_fired()); - EXPECT_TRUE(obs2.observer_fired()); - - // Make sure obs2 still works after removing obs. - prefs.RemovePrefObserver(pref_name, &obs); - obs.Reset(L""); - obs2.Reset(new_pref_value); - // This should only fire the observer in obs2. - prefs.SetString(pref_name, new_pref_value); - EXPECT_FALSE(obs.observer_fired()); - EXPECT_TRUE(obs2.observer_fired()); - - // Ok, clean up. - prefs.RemovePrefObserver(pref_name, &obs2); -} - -// TODO(port): port this test to POSIX. -#if defined(OS_WIN) -TEST_F(PrefServiceTest, LocalizedPrefs) { - PrefService prefs((FilePath())); - const wchar_t kBoolean[] = L"boolean"; - const wchar_t kInteger[] = L"integer"; - const wchar_t kString[] = L"string"; - prefs.RegisterLocalizedBooleanPref(kBoolean, IDS_LOCALE_BOOL); - prefs.RegisterLocalizedIntegerPref(kInteger, IDS_LOCALE_INT); - prefs.RegisterLocalizedStringPref(kString, IDS_LOCALE_STRING); - - // The locale default should take preference over the user default. - EXPECT_FALSE(prefs.GetBoolean(kBoolean)); - EXPECT_EQ(1, prefs.GetInteger(kInteger)); - EXPECT_EQ(L"hello", prefs.GetString(kString)); - - prefs.SetBoolean(kBoolean, true); - EXPECT_TRUE(prefs.GetBoolean(kBoolean)); - prefs.SetInteger(kInteger, 5); - EXPECT_EQ(5, prefs.GetInteger(kInteger)); - prefs.SetString(kString, L"foo"); - EXPECT_EQ(L"foo", prefs.GetString(kString)); -} -#endif - -TEST_F(PrefServiceTest, NoObserverFire) { - PrefService prefs((FilePath())); - - const wchar_t pref_name[] = L"homepage"; - prefs.RegisterStringPref(pref_name, L""); - - const std::wstring new_pref_value(L"http://www.google.com/"); - TestPrefObserver obs(&prefs, pref_name, new_pref_value); - prefs.AddPrefObserver(pref_name, &obs); - // This should fire the checks in TestPrefObserver::Observe. - prefs.SetString(pref_name, new_pref_value); - - // Make sure the observer was actually fired. - EXPECT_TRUE(obs.observer_fired()); - - // Setting the pref to the same value should not set the pref value a second - // time. - obs.Reset(new_pref_value); - prefs.SetString(pref_name, new_pref_value); - EXPECT_FALSE(obs.observer_fired()); - - // Clearing the pref should cause the pref to fire. - obs.Reset(L""); - prefs.ClearPref(pref_name); - EXPECT_TRUE(obs.observer_fired()); - - // Clearing the pref again should not cause the pref to fire. - obs.Reset(L""); - prefs.ClearPref(pref_name); - EXPECT_FALSE(obs.observer_fired()); - - // Ok, clean up. - prefs.RemovePrefObserver(pref_name, &obs); -} - -TEST_F(PrefServiceTest, HasPrefPath) { - PrefService prefs((FilePath())); - - const wchar_t path[] = L"fake.path"; - - // Shouldn't initially have a path. - EXPECT_FALSE(prefs.HasPrefPath(path)); - - // Register the path. This doesn't set a value, so the path still shouldn't - // exist. - prefs.RegisterStringPref(path, std::wstring()); - EXPECT_FALSE(prefs.HasPrefPath(path)); - - // Set a value and make sure we have a path. - prefs.SetString(path, L"blah"); - EXPECT_TRUE(prefs.HasPrefPath(path)); -} |