OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/prefs/pref_member.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/logging.h" | |
9 #include "base/value_conversions.h" | |
10 #include "chrome/browser/prefs/pref_service.h" | |
11 #include "chrome/common/chrome_notification_types.h" | |
12 | |
13 using content::BrowserThread; | |
14 | |
15 namespace subtle { | |
16 | |
17 PrefMemberBase::PrefMemberBase() | |
18 : observer_(NULL), | |
19 prefs_(NULL), | |
20 setting_value_(false) { | |
21 } | |
22 | |
23 PrefMemberBase::~PrefMemberBase() { | |
24 Destroy(); | |
25 } | |
26 | |
27 | |
28 void PrefMemberBase::Init(const char* pref_name, | |
29 PrefService* prefs, | |
30 content::NotificationObserver* observer) { | |
31 DCHECK(pref_name); | |
32 DCHECK(prefs); | |
33 DCHECK(pref_name_.empty()); // Check that Init is only called once. | |
34 observer_ = observer; | |
35 prefs_ = prefs; | |
36 pref_name_ = pref_name; | |
37 // Check that the preference is registered. | |
38 DCHECK(prefs_->FindPreference(pref_name_.c_str())) | |
39 << pref_name << " not registered."; | |
40 | |
41 // Add ourselves as a pref observer so we can keep our local value in sync. | |
42 prefs_->AddPrefObserver(pref_name, this); | |
43 } | |
44 | |
45 void PrefMemberBase::Destroy() { | |
46 if (prefs_ && !pref_name_.empty()) { | |
47 prefs_->RemovePrefObserver(pref_name_.c_str(), this); | |
48 prefs_ = NULL; | |
49 } | |
50 } | |
51 | |
52 void PrefMemberBase::MoveToThread(BrowserThread::ID thread_id) { | |
53 VerifyValuePrefName(); | |
54 // Load the value from preferences if it hasn't been loaded so far. | |
55 if (!internal()) | |
56 UpdateValueFromPref(); | |
57 internal()->MoveToThread(thread_id); | |
58 } | |
59 | |
60 void PrefMemberBase::Observe(int type, | |
61 const content::NotificationSource& source, | |
62 const content::NotificationDetails& details) { | |
63 VerifyValuePrefName(); | |
64 DCHECK(chrome::NOTIFICATION_PREF_CHANGED == type); | |
65 UpdateValueFromPref(); | |
66 if (!setting_value_ && observer_) | |
67 observer_->Observe(type, source, details); | |
68 } | |
69 | |
70 void PrefMemberBase::UpdateValueFromPref() const { | |
71 VerifyValuePrefName(); | |
72 const PrefService::Preference* pref = | |
73 prefs_->FindPreference(pref_name_.c_str()); | |
74 DCHECK(pref); | |
75 if (!internal()) | |
76 CreateInternal(); | |
77 internal()->UpdateValue(pref->GetValue()->DeepCopy(), pref->IsManaged()); | |
78 } | |
79 | |
80 void PrefMemberBase::VerifyPref() const { | |
81 VerifyValuePrefName(); | |
82 if (!internal()) | |
83 UpdateValueFromPref(); | |
84 } | |
85 | |
86 PrefMemberBase::Internal::Internal() | |
87 : thread_id_(BrowserThread::UI), | |
88 is_managed_(false) { | |
89 } | |
90 PrefMemberBase::Internal::~Internal() { } | |
91 | |
92 bool PrefMemberBase::Internal::IsOnCorrectThread() const { | |
93 // In unit tests, there may not be a UI thread. | |
94 return (BrowserThread::CurrentlyOn(thread_id_) || | |
95 (thread_id_ == BrowserThread::UI && | |
96 !BrowserThread::IsMessageLoopValid(BrowserThread::UI))); | |
97 } | |
98 | |
99 void PrefMemberBase::Internal::UpdateValue(Value* v, bool is_managed) const { | |
100 scoped_ptr<Value> value(v); | |
101 if (IsOnCorrectThread()) { | |
102 bool rv = UpdateValueInternal(*value); | |
103 DCHECK(rv); | |
104 is_managed_ = is_managed; | |
105 } else { | |
106 bool rv = BrowserThread::PostTask( | |
107 thread_id_, FROM_HERE, | |
108 base::Bind(&PrefMemberBase::Internal::UpdateValue, this, | |
109 value.release(), is_managed)); | |
110 DCHECK(rv); | |
111 } | |
112 } | |
113 | |
114 void PrefMemberBase::Internal::MoveToThread(BrowserThread::ID thread_id) { | |
115 CheckOnCorrectThread(); | |
116 thread_id_ = thread_id; | |
117 } | |
118 | |
119 } // namespace subtle | |
120 | |
121 template <> | |
122 void PrefMember<bool>::UpdatePref(const bool& value) { | |
123 prefs()->SetBoolean(pref_name().c_str(), value); | |
124 } | |
125 | |
126 template <> | |
127 bool PrefMember<bool>::Internal::UpdateValueInternal(const Value& value) const { | |
128 return value.GetAsBoolean(&value_); | |
129 } | |
130 | |
131 template <> | |
132 void PrefMember<int>::UpdatePref(const int& value) { | |
133 prefs()->SetInteger(pref_name().c_str(), value); | |
134 } | |
135 | |
136 template <> | |
137 bool PrefMember<int>::Internal::UpdateValueInternal(const Value& value) const { | |
138 return value.GetAsInteger(&value_); | |
139 } | |
140 | |
141 template <> | |
142 void PrefMember<double>::UpdatePref(const double& value) { | |
143 prefs()->SetDouble(pref_name().c_str(), value); | |
144 } | |
145 | |
146 template <> | |
147 bool PrefMember<double>::Internal::UpdateValueInternal(const Value& value) | |
148 const { | |
149 return value.GetAsDouble(&value_); | |
150 } | |
151 | |
152 template <> | |
153 void PrefMember<std::string>::UpdatePref(const std::string& value) { | |
154 prefs()->SetString(pref_name().c_str(), value); | |
155 } | |
156 | |
157 template <> | |
158 bool PrefMember<std::string>::Internal::UpdateValueInternal(const Value& value) | |
159 const { | |
160 return value.GetAsString(&value_); | |
161 } | |
162 | |
163 template <> | |
164 void PrefMember<FilePath>::UpdatePref(const FilePath& value) { | |
165 prefs()->SetFilePath(pref_name().c_str(), value); | |
166 } | |
167 | |
168 template <> | |
169 bool PrefMember<FilePath>::Internal::UpdateValueInternal(const Value& value) | |
170 const { | |
171 return base::GetValueAsFilePath(value, &value_); | |
172 } | |
OLD | NEW |