/src/mozilla-central/gfx/config/gfxFeature.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #include "gfxFeature.h" |
8 | | |
9 | | #include "mozilla/Preferences.h" |
10 | | #include "mozilla/Sprintf.h" |
11 | | #include "nsString.h" |
12 | | |
13 | | namespace mozilla { |
14 | | namespace gfx { |
15 | | |
16 | | bool |
17 | | FeatureState::IsEnabled() const |
18 | 0 | { |
19 | 0 | return IsInitialized() && IsFeatureStatusSuccess(GetValue()); |
20 | 0 | } |
21 | | |
22 | | FeatureStatus |
23 | | FeatureState::GetValue() const |
24 | 0 | { |
25 | 0 | if (!IsInitialized()) { |
26 | 0 | return FeatureStatus::Unused; |
27 | 0 | } |
28 | 0 | |
29 | 0 | if (mRuntime.mStatus != FeatureStatus::Unused) { |
30 | 0 | return mRuntime.mStatus; |
31 | 0 | } |
32 | 0 | if (mUser.mStatus == FeatureStatus::ForceEnabled) { |
33 | 0 | return FeatureStatus::ForceEnabled; |
34 | 0 | } |
35 | 0 | if (mEnvironment.mStatus != FeatureStatus::Unused) { |
36 | 0 | return mEnvironment.mStatus; |
37 | 0 | } |
38 | 0 | if (mUser.mStatus != FeatureStatus::Unused) { |
39 | 0 | return mUser.mStatus; |
40 | 0 | } |
41 | 0 | return mDefault.mStatus; |
42 | 0 | } |
43 | | |
44 | | bool |
45 | | FeatureState::SetDefault(bool aEnable, |
46 | | FeatureStatus aDisableStatus, |
47 | | const char* aDisableMessage) |
48 | 0 | { |
49 | 0 | if (!aEnable) { |
50 | 0 | DisableByDefault(aDisableStatus, aDisableMessage, |
51 | 0 | NS_LITERAL_CSTRING("FEATURE_FAILURE_DISABLED")); |
52 | 0 | return false; |
53 | 0 | } |
54 | 0 | EnableByDefault(); |
55 | 0 | return true; |
56 | 0 | } |
57 | | |
58 | | void |
59 | | FeatureState::SetDefaultFromPref(const char* aPrefName, |
60 | | bool aIsEnablePref, |
61 | | bool aDefaultValue) |
62 | 0 | { |
63 | 0 | bool baseValue = |
64 | 0 | Preferences::GetBool(aPrefName, aDefaultValue, PrefValueKind::Default); |
65 | 0 | SetDefault(baseValue == aIsEnablePref, FeatureStatus::Disabled, "Disabled by default"); |
66 | 0 |
|
67 | 0 | if (Preferences::HasUserValue(aPrefName)) { |
68 | 0 | bool userValue = Preferences::GetBool(aPrefName, aDefaultValue); |
69 | 0 | if (userValue == aIsEnablePref) { |
70 | 0 | nsCString message("Enabled via "); |
71 | 0 | message.AppendASCII(aPrefName); |
72 | 0 | UserEnable(message.get()); |
73 | 0 | } else { |
74 | 0 | nsCString message("Disabled via "); |
75 | 0 | message.AppendASCII(aPrefName); |
76 | 0 | UserDisable(message.get(), NS_LITERAL_CSTRING("FEATURE_FAILURE_PREF_OFF")); |
77 | 0 | } |
78 | 0 | } |
79 | 0 | } |
80 | | |
81 | | bool |
82 | | FeatureState::InitOrUpdate(bool aEnable, |
83 | | FeatureStatus aDisableStatus, |
84 | | const char* aDisableMessage) |
85 | 0 | { |
86 | 0 | if (!IsInitialized()) { |
87 | 0 | return SetDefault(aEnable, aDisableStatus, aDisableMessage); |
88 | 0 | } |
89 | 0 | return MaybeSetFailed(aEnable, aDisableStatus, aDisableMessage, nsCString()); |
90 | 0 | } |
91 | | |
92 | | void |
93 | | FeatureState::UserEnable(const char* aMessage) |
94 | 0 | { |
95 | 0 | AssertInitialized(); |
96 | 0 | SetUser(FeatureStatus::Available, aMessage); |
97 | 0 | } |
98 | | |
99 | | void |
100 | | FeatureState::UserForceEnable(const char* aMessage) |
101 | 0 | { |
102 | 0 | AssertInitialized(); |
103 | 0 | SetUser(FeatureStatus::ForceEnabled, aMessage); |
104 | 0 | } |
105 | | |
106 | | void |
107 | | FeatureState::UserDisable(const char* aMessage, const nsACString& aFailureId) |
108 | 0 | { |
109 | 0 | AssertInitialized(); |
110 | 0 | SetUser(FeatureStatus::Disabled, aMessage); |
111 | 0 | SetFailureId(aFailureId); |
112 | 0 | } |
113 | | |
114 | | void |
115 | | FeatureState::Disable(FeatureStatus aStatus, const char* aMessage, |
116 | | const nsACString& aFailureId) |
117 | 0 | { |
118 | 0 | AssertInitialized(); |
119 | 0 |
|
120 | 0 | // We should never bother setting an environment status to "enabled," since |
121 | 0 | // it could override an explicit user decision to disable it. |
122 | 0 | MOZ_ASSERT(IsFeatureStatusFailure(aStatus)); |
123 | 0 |
|
124 | 0 | SetEnvironment(aStatus, aMessage); |
125 | 0 | SetFailureId(aFailureId); |
126 | 0 | } |
127 | | |
128 | | void |
129 | | FeatureState::SetFailed(FeatureStatus aStatus, const char* aMessage, |
130 | | const nsACString& aFailureId) |
131 | 0 | { |
132 | 0 | AssertInitialized(); |
133 | 0 |
|
134 | 0 | // We should never bother setting a runtime status to "enabled," since it could |
135 | 0 | // override an explicit user decision to disable it. |
136 | 0 | MOZ_ASSERT(IsFeatureStatusFailure(aStatus)); |
137 | 0 |
|
138 | 0 | SetRuntime(aStatus, aMessage); |
139 | 0 | SetFailureId(aFailureId); |
140 | 0 | } |
141 | | |
142 | | bool |
143 | | FeatureState::MaybeSetFailed(bool aEnable, FeatureStatus aStatus, const char* aMessage, |
144 | | const nsACString& aFailureId) |
145 | 0 | { |
146 | 0 | if (!aEnable) { |
147 | 0 | SetFailed(aStatus, aMessage, aFailureId); |
148 | 0 | return false; |
149 | 0 | } |
150 | 0 | return true; |
151 | 0 | } |
152 | | |
153 | | bool |
154 | | FeatureState::MaybeSetFailed(FeatureStatus aStatus, const char* aMessage, |
155 | | const nsACString& aFailureId) |
156 | 0 | { |
157 | 0 | return MaybeSetFailed(IsFeatureStatusSuccess(aStatus), aStatus, aMessage, |
158 | 0 | aFailureId); |
159 | 0 | } |
160 | | |
161 | | bool |
162 | | FeatureState::DisabledByDefault() const |
163 | 0 | { |
164 | 0 | return mDefault.mStatus != FeatureStatus::Available; |
165 | 0 | } |
166 | | |
167 | | bool |
168 | | FeatureState::IsForcedOnByUser() const |
169 | 0 | { |
170 | 0 | AssertInitialized(); |
171 | 0 | return mUser.mStatus == FeatureStatus::ForceEnabled; |
172 | 0 | } |
173 | | |
174 | | void |
175 | | FeatureState::EnableByDefault() |
176 | 0 | { |
177 | 0 | // User/runtime decisions should not have been made yet. |
178 | 0 | MOZ_ASSERT(!mUser.IsInitialized()); |
179 | 0 | MOZ_ASSERT(!mEnvironment.IsInitialized()); |
180 | 0 | MOZ_ASSERT(!mRuntime.IsInitialized()); |
181 | 0 |
|
182 | 0 | mDefault.Set(FeatureStatus::Available); |
183 | 0 | } |
184 | | |
185 | | void |
186 | | FeatureState::DisableByDefault(FeatureStatus aStatus, const char* aMessage, |
187 | | const nsACString& aFailureId) |
188 | 0 | { |
189 | 0 | // User/runtime decisions should not have been made yet. |
190 | 0 | MOZ_ASSERT(!mUser.IsInitialized()); |
191 | 0 | MOZ_ASSERT(!mEnvironment.IsInitialized()); |
192 | 0 | MOZ_ASSERT(!mRuntime.IsInitialized()); |
193 | 0 |
|
194 | 0 | // Make sure that when disabling we actually use a failure status. |
195 | 0 | MOZ_ASSERT(IsFeatureStatusFailure(aStatus)); |
196 | 0 |
|
197 | 0 | mDefault.Set(aStatus, aMessage); |
198 | 0 | SetFailureId(aFailureId); |
199 | 0 | } |
200 | | |
201 | | void |
202 | | FeatureState::SetUser(FeatureStatus aStatus, const char* aMessage) |
203 | 0 | { |
204 | 0 | // Default decision must have been made, but not runtime or environment. |
205 | 0 | MOZ_ASSERT(mDefault.IsInitialized()); |
206 | 0 | MOZ_ASSERT(!mEnvironment.IsInitialized()); |
207 | 0 | MOZ_ASSERT(!mRuntime.IsInitialized()); |
208 | 0 |
|
209 | 0 | mUser.Set(aStatus, aMessage); |
210 | 0 | } |
211 | | |
212 | | void |
213 | | FeatureState::SetEnvironment(FeatureStatus aStatus, const char* aMessage) |
214 | 0 | { |
215 | 0 | // Default decision must have been made, but not runtime. |
216 | 0 | MOZ_ASSERT(mDefault.IsInitialized()); |
217 | 0 | MOZ_ASSERT(!mRuntime.IsInitialized()); |
218 | 0 |
|
219 | 0 | mEnvironment.Set(aStatus, aMessage); |
220 | 0 | } |
221 | | |
222 | | void |
223 | | FeatureState::SetRuntime(FeatureStatus aStatus, const char* aMessage) |
224 | 0 | { |
225 | 0 | AssertInitialized(); |
226 | 0 |
|
227 | 0 | mRuntime.Set(aStatus, aMessage); |
228 | 0 | } |
229 | | |
230 | | const char* |
231 | | FeatureState::GetRuntimeMessage() const |
232 | 0 | { |
233 | 0 | MOZ_ASSERT(IsFeatureStatusFailure(mRuntime.mStatus)); |
234 | 0 | return mRuntime.mMessage; |
235 | 0 | } |
236 | | |
237 | | void |
238 | | FeatureState::ForEachStatusChange(const StatusIterCallback& aCallback) const |
239 | 0 | { |
240 | 0 | AssertInitialized(); |
241 | 0 |
|
242 | 0 | aCallback("default", mDefault.mStatus, mDefault.MessageOrNull()); |
243 | 0 | if (mUser.IsInitialized()) { |
244 | 0 | aCallback("user", mUser.mStatus, mUser.Message()); |
245 | 0 | } |
246 | 0 | if (mEnvironment.IsInitialized()) { |
247 | 0 | aCallback("env", mEnvironment.mStatus, mEnvironment.Message()); |
248 | 0 | } |
249 | 0 | if (mRuntime.IsInitialized()) { |
250 | 0 | aCallback("runtime", mRuntime.mStatus, mRuntime.Message()); |
251 | 0 | } |
252 | 0 | } |
253 | | |
254 | | void |
255 | | FeatureState::SetFailureId(const nsACString& aFailureId) |
256 | 0 | { |
257 | 0 | if (mFailureId.IsEmpty()) { |
258 | 0 | mFailureId = aFailureId; |
259 | 0 | } |
260 | 0 | } |
261 | | |
262 | | const char* |
263 | | FeatureState::GetFailureMessage() const |
264 | 0 | { |
265 | 0 | AssertInitialized(); |
266 | 0 | MOZ_ASSERT(!IsEnabled()); |
267 | 0 |
|
268 | 0 | if (mRuntime.mStatus != FeatureStatus::Unused && |
269 | 0 | IsFeatureStatusFailure(mRuntime.mStatus)) |
270 | 0 | { |
271 | 0 | return mRuntime.mMessage; |
272 | 0 | } |
273 | 0 | if (mEnvironment.mStatus != FeatureStatus::Unused && |
274 | 0 | IsFeatureStatusFailure(mEnvironment.mStatus)) |
275 | 0 | { |
276 | 0 | return mEnvironment.mMessage; |
277 | 0 | } |
278 | 0 | if (mUser.mStatus != FeatureStatus::Unused && |
279 | 0 | IsFeatureStatusFailure(mUser.mStatus)) |
280 | 0 | { |
281 | 0 | return mUser.mMessage; |
282 | 0 | } |
283 | 0 | |
284 | 0 | MOZ_ASSERT(IsFeatureStatusFailure(mDefault.mStatus)); |
285 | 0 | return mDefault.mMessage; |
286 | 0 | } |
287 | | |
288 | | const nsCString& |
289 | | FeatureState::GetFailureId() const |
290 | 0 | { |
291 | 0 | MOZ_ASSERT(!IsEnabled()); |
292 | 0 | return mFailureId; |
293 | 0 | } |
294 | | |
295 | | void |
296 | | FeatureState::Reset() |
297 | 0 | { |
298 | 0 | mDefault.Set(FeatureStatus::Unused); |
299 | 0 | mUser.Set(FeatureStatus::Unused); |
300 | 0 | mEnvironment.Set(FeatureStatus::Unused); |
301 | 0 | mRuntime.Set(FeatureStatus::Unused); |
302 | 0 | mFailureId = nsCString(); |
303 | 0 | } |
304 | | |
305 | | void |
306 | | FeatureState::Instance::Set(FeatureStatus aStatus, const char* aMessage /* = nullptr */) |
307 | 0 | { |
308 | 0 | mStatus = aStatus; |
309 | 0 | if (aMessage) { |
310 | 0 | SprintfLiteral(mMessage, "%s", aMessage); |
311 | 0 | } else { |
312 | 0 | mMessage[0] = '\0'; |
313 | 0 | } |
314 | 0 | } |
315 | | |
316 | | } // namespace gfx |
317 | | } // namespace mozilla |