Bug 1885580 - Add a MenuGroup component for the menu redesign r=android-reviewers,007
[gecko.git] / gfx / config / gfxFeature.cpp
blobfe40bf02ea8a429ad06e24651cb8b0fbd05b9adc
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/. */
7 #include "gfxFeature.h"
9 #include "mozilla/Preferences.h"
10 #include "mozilla/Sprintf.h"
11 #include "nsString.h"
13 namespace mozilla {
14 namespace gfx {
16 bool FeatureState::IsEnabled() const {
17 return IsInitialized() && IsFeatureStatusSuccess(GetValue());
20 FeatureStatus FeatureState::GetValue() const {
21 if (!IsInitialized()) {
22 return FeatureStatus::Unused;
25 if (mRuntime.mStatus != FeatureStatus::Unused) {
26 return mRuntime.mStatus;
28 if (mUser.mStatus == FeatureStatus::ForceEnabled) {
29 return FeatureStatus::ForceEnabled;
31 if (mEnvironment.mStatus != FeatureStatus::Unused) {
32 return mEnvironment.mStatus;
34 if (mUser.mStatus != FeatureStatus::Unused) {
35 return mUser.mStatus;
37 return mDefault.mStatus;
40 bool FeatureState::SetDefault(bool aEnable, FeatureStatus aDisableStatus,
41 const char* aDisableMessage) {
42 if (!aEnable) {
43 DisableByDefault(aDisableStatus, aDisableMessage,
44 "FEATURE_FAILURE_DISABLED"_ns);
45 return false;
47 EnableByDefault();
48 return true;
51 void FeatureState::SetDefaultFromPref(const char* aPrefName, bool aIsEnablePref,
52 bool aDefaultValue,
53 Maybe<bool> aUserValue) {
54 bool baseValue =
55 Preferences::GetBool(aPrefName, aDefaultValue, PrefValueKind::Default);
56 SetDefault(baseValue == aIsEnablePref, FeatureStatus::Disabled,
57 "Disabled by default");
59 if (aUserValue) {
60 if (*aUserValue == aIsEnablePref) {
61 nsCString message("Enabled via ");
62 message.AppendASCII(aPrefName);
63 UserEnable(message.get());
64 } else {
65 nsCString message("Disabled via ");
66 message.AppendASCII(aPrefName);
67 UserDisable(message.get(), "FEATURE_FAILURE_PREF_OFF"_ns);
72 void FeatureState::SetDefaultFromPref(const char* aPrefName, bool aIsEnablePref,
73 bool aDefaultValue) {
74 Maybe<bool> userValue;
75 if (Preferences::HasUserValue(aPrefName)) {
76 userValue.emplace(Preferences::GetBool(aPrefName, aDefaultValue));
79 SetDefaultFromPref(aPrefName, aIsEnablePref, aDefaultValue, userValue);
82 bool FeatureState::InitOrUpdate(bool aEnable, FeatureStatus aDisableStatus,
83 const char* aDisableMessage) {
84 if (!IsInitialized()) {
85 return SetDefault(aEnable, aDisableStatus, aDisableMessage);
87 return MaybeSetFailed(aEnable, aDisableStatus, aDisableMessage, nsCString());
90 void FeatureState::UserEnable(const char* aMessage) {
91 AssertInitialized();
92 SetUser(FeatureStatus::Available, aMessage, nsCString());
95 void FeatureState::UserForceEnable(const char* aMessage) {
96 AssertInitialized();
97 SetUser(FeatureStatus::ForceEnabled, aMessage, nsCString());
100 void FeatureState::UserDisable(const char* aMessage,
101 const nsACString& aFailureId) {
102 AssertInitialized();
103 SetUser(FeatureStatus::Disabled, aMessage, aFailureId);
106 void FeatureState::Disable(FeatureStatus aStatus, const char* aMessage,
107 const nsACString& aFailureId) {
108 AssertInitialized();
110 // We should never bother setting an environment status to "enabled," since
111 // it could override an explicit user decision to disable it.
112 MOZ_ASSERT(IsFeatureStatusFailure(aStatus));
114 SetEnvironment(aStatus, aMessage, aFailureId);
117 void FeatureState::SetFailed(FeatureStatus aStatus, const char* aMessage,
118 const nsACString& aFailureId) {
119 AssertInitialized();
121 // We should never bother setting a runtime status to "enabled," since it
122 // could override an explicit user decision to disable it.
123 MOZ_ASSERT(IsFeatureStatusFailure(aStatus));
125 SetRuntime(aStatus, aMessage, aFailureId);
128 bool FeatureState::MaybeSetFailed(bool aEnable, FeatureStatus aStatus,
129 const char* aMessage,
130 const nsACString& aFailureId) {
131 if (!aEnable) {
132 SetFailed(aStatus, aMessage, aFailureId);
133 return false;
135 return true;
138 bool FeatureState::MaybeSetFailed(FeatureStatus aStatus, const char* aMessage,
139 const nsACString& aFailureId) {
140 return MaybeSetFailed(IsFeatureStatusSuccess(aStatus), aStatus, aMessage,
141 aFailureId);
144 bool FeatureState::DisabledByDefault() const {
145 return mDefault.mStatus != FeatureStatus::Available;
148 bool FeatureState::IsForcedOnByUser() const {
149 AssertInitialized();
150 return mUser.mStatus == FeatureStatus::ForceEnabled;
153 void FeatureState::EnableByDefault() {
154 // User/runtime decisions should not have been made yet.
155 MOZ_ASSERT(!mUser.IsInitialized());
156 MOZ_ASSERT(!mEnvironment.IsInitialized());
157 MOZ_ASSERT(!mRuntime.IsInitialized());
159 mDefault.Set(FeatureStatus::Available);
162 void FeatureState::DisableByDefault(FeatureStatus aStatus, const char* aMessage,
163 const nsACString& aFailureId) {
164 // User/runtime decisions should not have been made yet.
165 MOZ_ASSERT(!mUser.IsInitialized());
166 MOZ_ASSERT(!mEnvironment.IsInitialized());
167 MOZ_ASSERT(!mRuntime.IsInitialized());
169 // Make sure that when disabling we actually use a failure status.
170 MOZ_ASSERT(IsFeatureStatusFailure(aStatus));
172 mDefault.Set(aStatus, aMessage, aFailureId);
175 void FeatureState::SetUser(FeatureStatus aStatus, const char* aMessage,
176 const nsACString& aFailureId) {
177 // Default decision must have been made, but not runtime or environment.
178 MOZ_ASSERT(mDefault.IsInitialized());
179 MOZ_ASSERT(!mEnvironment.IsInitialized());
180 MOZ_ASSERT(!mRuntime.IsInitialized());
182 mUser.Set(aStatus, aMessage, aFailureId);
185 void FeatureState::SetEnvironment(FeatureStatus aStatus, const char* aMessage,
186 const nsACString& aFailureId) {
187 // Default decision must have been made, but not runtime.
188 MOZ_ASSERT(mDefault.IsInitialized());
189 MOZ_ASSERT(!mRuntime.IsInitialized());
191 mEnvironment.Set(aStatus, aMessage, aFailureId);
194 void FeatureState::SetRuntime(FeatureStatus aStatus, const char* aMessage,
195 const nsACString& aFailureId) {
196 AssertInitialized();
198 mRuntime.Set(aStatus, aMessage, aFailureId);
201 const char* FeatureState::GetRuntimeMessage() const {
202 MOZ_ASSERT(IsFeatureStatusFailure(mRuntime.mStatus));
203 return mRuntime.mMessage;
206 void FeatureState::ForEachStatusChange(
207 const StatusIterCallback& aCallback) const {
208 AssertInitialized();
210 aCallback("default", mDefault.mStatus, mDefault.MessageOrNull(),
211 mDefault.FailureId());
212 if (mUser.IsInitialized()) {
213 aCallback("user", mUser.mStatus, mUser.Message(), mUser.FailureId());
215 if (mEnvironment.IsInitialized()) {
216 aCallback("env", mEnvironment.mStatus, mEnvironment.Message(),
217 mEnvironment.FailureId());
219 if (mRuntime.IsInitialized()) {
220 aCallback("runtime", mRuntime.mStatus, mRuntime.Message(),
221 mRuntime.FailureId());
225 const char* FeatureState::GetFailureMessage() const {
226 AssertInitialized();
227 MOZ_ASSERT(!IsEnabled());
229 if (mRuntime.mStatus != FeatureStatus::Unused &&
230 IsFeatureStatusFailure(mRuntime.mStatus)) {
231 return mRuntime.mMessage;
233 if (mEnvironment.mStatus != FeatureStatus::Unused &&
234 IsFeatureStatusFailure(mEnvironment.mStatus)) {
235 return mEnvironment.mMessage;
237 if (mUser.mStatus != FeatureStatus::Unused &&
238 IsFeatureStatusFailure(mUser.mStatus)) {
239 return mUser.mMessage;
242 MOZ_ASSERT(IsFeatureStatusFailure(mDefault.mStatus));
243 return mDefault.mMessage;
246 const nsCString& FeatureState::GetFailureId() const {
247 MOZ_ASSERT(!IsEnabled());
249 if (mRuntime.mStatus != FeatureStatus::Unused) {
250 return mRuntime.mFailureId;
252 if (mEnvironment.mStatus != FeatureStatus::Unused) {
253 return mEnvironment.mFailureId;
255 if (mUser.mStatus != FeatureStatus::Unused) {
256 return mUser.mFailureId;
259 return mDefault.mFailureId;
262 nsCString FeatureState::GetStatusAndFailureIdString() const {
263 nsCString status;
264 auto value = GetValue();
265 switch (value) {
266 case FeatureStatus::Blocklisted:
267 case FeatureStatus::Disabled:
268 case FeatureStatus::Unavailable:
269 case FeatureStatus::UnavailableNoAngle:
270 case FeatureStatus::Blocked:
271 status.AppendPrintf("%s:%s", FeatureStatusToString(value),
272 GetFailureId().get());
273 break;
274 case FeatureStatus::Failed:
275 status.AppendPrintf("%s:%s", FeatureStatusToString(value),
276 GetFailureMessage());
277 break;
278 default:
279 status.Append(FeatureStatusToString(value));
280 break;
283 return status;
286 void FeatureState::Reset() {
287 mDefault.Set(FeatureStatus::Unused);
288 mUser.Set(FeatureStatus::Unused);
289 mEnvironment.Set(FeatureStatus::Unused);
290 mRuntime.Set(FeatureStatus::Unused);
293 void FeatureState::Instance::Set(FeatureStatus aStatus) {
294 mStatus = aStatus;
295 mMessage[0] = '\0';
296 mFailureId.Truncate();
299 void FeatureState::Instance::Set(FeatureStatus aStatus, const char* aMessage,
300 const nsACString& aFailureId) {
301 mStatus = aStatus;
302 if (aMessage) {
303 SprintfLiteral(mMessage, "%s", aMessage);
304 } else {
305 mMessage[0] = '\0';
307 mFailureId.Assign(aFailureId);
310 } // namespace gfx
311 } // namespace mozilla