tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

gfxFeature.cpp (9694B)


      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 FeatureState::IsEnabled() const {
     17  return IsInitialized() && IsFeatureStatusSuccess(GetValue());
     18 }
     19 
     20 FeatureStatus FeatureState::GetValue() const {
     21  if (!IsInitialized()) {
     22    return FeatureStatus::Unused;
     23  }
     24 
     25  if (mRuntime.mStatus != FeatureStatus::Unused) {
     26    return mRuntime.mStatus;
     27  }
     28  if (mUser.mStatus == FeatureStatus::ForceEnabled) {
     29    return FeatureStatus::ForceEnabled;
     30  }
     31  if (mEnvironment.mStatus != FeatureStatus::Unused) {
     32    return mEnvironment.mStatus;
     33  }
     34  if (mUser.mStatus != FeatureStatus::Unused) {
     35    return mUser.mStatus;
     36  }
     37  return mDefault.mStatus;
     38 }
     39 
     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;
     46  }
     47  EnableByDefault();
     48  return true;
     49 }
     50 
     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");
     58 
     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);
     68    }
     69  }
     70 }
     71 
     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));
     77  }
     78 
     79  SetDefaultFromPref(aPrefName, aIsEnablePref, aDefaultValue, userValue);
     80 }
     81 
     82 bool FeatureState::InitOrUpdate(bool aEnable, FeatureStatus aDisableStatus,
     83                                const char* aDisableMessage) {
     84  if (!IsInitialized()) {
     85    return SetDefault(aEnable, aDisableStatus, aDisableMessage);
     86  }
     87  return MaybeSetFailed(aEnable, aDisableStatus, aDisableMessage, nsCString());
     88 }
     89 
     90 void FeatureState::UserEnable(const char* aMessage) {
     91  AssertInitialized();
     92  SetUser(FeatureStatus::Available, aMessage, nsCString());
     93 }
     94 
     95 void FeatureState::UserForceEnable(const char* aMessage) {
     96  AssertInitialized();
     97  SetUser(FeatureStatus::ForceEnabled, aMessage, nsCString());
     98 }
     99 
    100 void FeatureState::UserDisable(const char* aMessage,
    101                               const nsACString& aFailureId) {
    102  AssertInitialized();
    103  SetUser(FeatureStatus::Disabled, aMessage, aFailureId);
    104 }
    105 
    106 void FeatureState::Disable(FeatureStatus aStatus, const char* aMessage,
    107                           const nsACString& aFailureId) {
    108  AssertInitialized();
    109 
    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));
    113 
    114  SetEnvironment(aStatus, aMessage, aFailureId);
    115 }
    116 
    117 void FeatureState::SetFailed(FeatureStatus aStatus, const char* aMessage,
    118                             const nsACString& aFailureId) {
    119  AssertInitialized();
    120 
    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));
    124 
    125  SetRuntime(aStatus, aMessage, aFailureId);
    126 }
    127 
    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;
    134  }
    135  return true;
    136 }
    137 
    138 bool FeatureState::MaybeSetFailed(FeatureStatus aStatus, const char* aMessage,
    139                                  const nsACString& aFailureId) {
    140  return MaybeSetFailed(IsFeatureStatusSuccess(aStatus), aStatus, aMessage,
    141                        aFailureId);
    142 }
    143 
    144 bool FeatureState::DisabledByDefault() const {
    145  return mDefault.mStatus != FeatureStatus::Available;
    146 }
    147 
    148 bool FeatureState::IsForcedOnByUser() const {
    149  AssertInitialized();
    150  return mUser.mStatus == FeatureStatus::ForceEnabled;
    151 }
    152 
    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());
    158 
    159  mDefault.Set(FeatureStatus::Available);
    160 }
    161 
    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());
    168 
    169  // Make sure that when disabling we actually use a failure status.
    170  MOZ_ASSERT(IsFeatureStatusFailure(aStatus));
    171 
    172  mDefault.Set(aStatus, aMessage, aFailureId);
    173 }
    174 
    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());
    181 
    182  mUser.Set(aStatus, aMessage, aFailureId);
    183 }
    184 
    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());
    190 
    191  mEnvironment.Set(aStatus, aMessage, aFailureId);
    192 }
    193 
    194 void FeatureState::SetRuntime(FeatureStatus aStatus, const char* aMessage,
    195                              const nsACString& aFailureId) {
    196  AssertInitialized();
    197 
    198  mRuntime.Set(aStatus, aMessage, aFailureId);
    199 }
    200 
    201 const char* FeatureState::GetRuntimeMessage() const {
    202  MOZ_ASSERT(IsFeatureStatusFailure(mRuntime.mStatus));
    203  return mRuntime.mMessage;
    204 }
    205 
    206 void FeatureState::ForEachStatusChange(
    207    const StatusIterCallback& aCallback) const {
    208  AssertInitialized();
    209 
    210  aCallback("default", mDefault.mStatus, mDefault.MessageOrNull(),
    211            mDefault.FailureId());
    212  if (mUser.IsInitialized()) {
    213    aCallback("user", mUser.mStatus, mUser.Message(), mUser.FailureId());
    214  }
    215  if (mEnvironment.IsInitialized()) {
    216    aCallback("env", mEnvironment.mStatus, mEnvironment.Message(),
    217              mEnvironment.FailureId());
    218  }
    219  if (mRuntime.IsInitialized()) {
    220    aCallback("runtime", mRuntime.mStatus, mRuntime.Message(),
    221              mRuntime.FailureId());
    222  }
    223 }
    224 
    225 const char* FeatureState::GetFailureMessage() const {
    226  AssertInitialized();
    227  MOZ_ASSERT(!IsEnabled());
    228 
    229  if (mRuntime.mStatus != FeatureStatus::Unused &&
    230      IsFeatureStatusFailure(mRuntime.mStatus)) {
    231    return mRuntime.mMessage;
    232  }
    233  if (mEnvironment.mStatus != FeatureStatus::Unused &&
    234      IsFeatureStatusFailure(mEnvironment.mStatus)) {
    235    return mEnvironment.mMessage;
    236  }
    237  if (mUser.mStatus != FeatureStatus::Unused &&
    238      IsFeatureStatusFailure(mUser.mStatus)) {
    239    return mUser.mMessage;
    240  }
    241 
    242  MOZ_ASSERT(IsFeatureStatusFailure(mDefault.mStatus));
    243  return mDefault.mMessage;
    244 }
    245 
    246 const nsCString& FeatureState::GetFailureId() const {
    247  MOZ_ASSERT(!IsEnabled());
    248 
    249  if (mRuntime.mStatus != FeatureStatus::Unused) {
    250    return mRuntime.mFailureId;
    251  }
    252  if (mEnvironment.mStatus != FeatureStatus::Unused) {
    253    return mEnvironment.mFailureId;
    254  }
    255  if (mUser.mStatus != FeatureStatus::Unused) {
    256    return mUser.mFailureId;
    257  }
    258 
    259  return mDefault.mFailureId;
    260 }
    261 
    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;
    281  }
    282 
    283  return status;
    284 }
    285 
    286 void FeatureState::Reset() {
    287  mDefault.Set(FeatureStatus::Unused);
    288  mUser.Set(FeatureStatus::Unused);
    289  mEnvironment.Set(FeatureStatus::Unused);
    290  mRuntime.Set(FeatureStatus::Unused);
    291 }
    292 
    293 void FeatureState::Instance::Set(FeatureStatus aStatus) {
    294  mStatus = aStatus;
    295  mMessage[0] = '\0';
    296  mFailureId.Truncate();
    297 }
    298 
    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';
    306  }
    307  mFailureId.Assign(aFailureId);
    308 }
    309 
    310 }  // namespace gfx
    311 }  // namespace mozilla