nsCSSProps.cpp (8577B)
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 /* 8 * methods for dealing with CSS properties and tables of the keyword 9 * values they accept 10 */ 11 12 #include "nsCSSProps.h" 13 14 #include "gfxPlatform.h" 15 #include "mozilla/ClearOnShutdown.h" 16 #include "mozilla/LookAndFeel.h" // for system colors 17 #include "mozilla/Preferences.h" 18 #include "mozilla/StaticPrefs_layout.h" 19 #include "mozilla/StaticPtr.h" 20 #include "mozilla/dom/Animation.h" 21 #include "mozilla/dom/AnimationEffectBinding.h" // for PlaybackDirection 22 #include "mozilla/gfx/gfxVarReceiver.h" 23 #include "mozilla/gfx/gfxVars.h" // for UseWebRender 24 #include "nsIWidget.h" 25 #include "nsLayoutUtils.h" 26 #include "nsStaticNameTable.h" 27 #include "nsString.h" 28 #include "nsStyleConsts.h" // For system widget appearance types 29 30 using namespace mozilla; 31 32 static StaticAutoPtr<nsStaticCaseInsensitiveNameTable> gFontDescTable; 33 static StaticAutoPtr<nsStaticCaseInsensitiveNameTable> gCounterDescTable; 34 static StaticAutoPtr<nsTHashMap<nsCStringHashKey, NonCustomCSSPropertyId>> 35 gPropertyIDLNameTable; 36 37 static constexpr const char* const kCSSRawFontDescs[] = { 38 #define CSS_FONT_DESC(name_, method_) #name_, 39 #include "nsCSSFontDescList.h" 40 #undef CSS_FONT_DESC 41 }; 42 43 static constexpr const char* const kCSSRawCounterDescs[] = { 44 #define CSS_COUNTER_DESC(name_, method_) #name_, 45 #include "nsCSSCounterDescList.h" 46 #undef CSS_COUNTER_DESC 47 }; 48 49 static constexpr CSSPropFlags kFlagsTable[eCSSProperty_COUNT_with_aliases] = { 50 #define CSS_PROP_LONGHAND(name_, id_, method_, flags_, ...) flags_, 51 #define CSS_PROP_SHORTHAND(name_, id_, method_, flags_, ...) flags_, 52 #define CSS_PROP_ALIAS(name_, aliasid_, id_, method_, flags_, ...) flags_, 53 #include "mozilla/ServoCSSPropList.h" 54 #undef CSS_PROP_ALIAS 55 #undef CSS_PROP_SHORTHAND 56 #undef CSS_PROP_LONGHAND 57 }; 58 59 static nsStaticCaseInsensitiveNameTable* CreateStaticTable( 60 const char* const aRawTable[], int32_t aLength) { 61 auto* table = new nsStaticCaseInsensitiveNameTable(aRawTable, aLength); 62 #ifdef DEBUG 63 // Partially verify the entries. 64 for (int32_t index = 0; index < aLength; ++index) { 65 nsAutoCString temp(aRawTable[index]); 66 MOZ_ASSERT(-1 == temp.FindChar('_'), 67 "underscore char in case insensitive name table"); 68 } 69 #endif 70 return table; 71 } 72 73 void nsCSSProps::RecomputeEnabledState(const char* aPref, void*) { 74 MOZ_RELEASE_ASSERT(NS_IsMainThread()); 75 DebugOnly<bool> foundPref = false; 76 for (const PropertyPref* pref = kPropertyPrefTable; 77 pref->mPropId != eCSSProperty_UNKNOWN; pref++) { 78 if (!aPref || !strcmp(aPref, pref->mPref)) { 79 foundPref = true; 80 gPropertyEnabled[pref->mPropId] = Preferences::GetBool(pref->mPref); 81 if (pref->mPropId == eCSSProperty_backdrop_filter) { 82 gPropertyEnabled[pref->mPropId] &= 83 gfx::gfxVars::GetAllowBackdropFilterOrDefault(); 84 } 85 #ifdef FUZZING 86 // In fuzzing builds we want to enable all properties unconditionally. 87 gPropertyEnabled[pref->mPropId] = true; 88 #endif 89 } 90 } 91 MOZ_ASSERT(foundPref); 92 } 93 94 void nsCSSProps::Init() { 95 MOZ_ASSERT(!gFontDescTable, "pre existing array!"); 96 MOZ_ASSERT(!gCounterDescTable, "pre existing array!"); 97 MOZ_ASSERT(!gPropertyIDLNameTable, "pre existing array!"); 98 99 gFontDescTable = CreateStaticTable(kCSSRawFontDescs, eCSSFontDesc_COUNT); 100 gCounterDescTable = 101 CreateStaticTable(kCSSRawCounterDescs, eCSSCounterDesc_COUNT); 102 103 gPropertyIDLNameTable = 104 new nsTHashMap<nsCStringHashKey, NonCustomCSSPropertyId>; 105 for (NonCustomCSSPropertyId p = NonCustomCSSPropertyId(0); 106 size_t(p) < std::size(kIDLNameTable); 107 p = NonCustomCSSPropertyId(p + 1)) { 108 if (kIDLNameTable[p]) { 109 gPropertyIDLNameTable->InsertOrUpdate( 110 nsDependentCString(kIDLNameTable[p]), p); 111 } 112 } 113 114 ClearOnShutdown(&gFontDescTable); 115 ClearOnShutdown(&gCounterDescTable); 116 ClearOnShutdown(&gPropertyIDLNameTable); 117 118 for (const PropertyPref* pref = kPropertyPrefTable; 119 pref->mPropId != eCSSProperty_UNKNOWN; pref++) { 120 // https://bugzilla.mozilla.org/show_bug.cgi?id=1472523 121 // We need to use nsCString instead of substring because the preference 122 // callback code stores them. Using AssignLiteral prevents any 123 // unnecessary allocations. 124 nsCString prefName; 125 prefName.AssignLiteral(pref->mPref, strlen(pref->mPref)); 126 Preferences::RegisterCallback(nsCSSProps::RecomputeEnabledState, prefName); 127 } 128 RecomputeEnabledState(/* aPrefName = */ nullptr); 129 } 130 131 /* static */ 132 bool nsCSSProps::IsCustomPropertyName(const nsACString& aProperty) { 133 return aProperty.Length() >= CSS_CUSTOM_NAME_PREFIX_LENGTH && 134 StringBeginsWith(aProperty, "--"_ns); 135 } 136 137 NonCustomCSSPropertyId nsCSSProps::LookupPropertyByIDLName( 138 const nsACString& aPropertyIDLName, EnabledState aEnabled) { 139 MOZ_ASSERT(gPropertyIDLNameTable, "no lookup table, needs addref"); 140 NonCustomCSSPropertyId res; 141 if (!gPropertyIDLNameTable->Get(aPropertyIDLName, &res)) { 142 return eCSSProperty_UNKNOWN; 143 } 144 MOZ_ASSERT(res < eCSSProperty_COUNT); 145 if (!IsEnabled(res, aEnabled)) { 146 return eCSSProperty_UNKNOWN; 147 } 148 return res; 149 } 150 151 nsCSSFontDesc nsCSSProps::LookupFontDesc(const nsACString& aFontDesc) { 152 MOZ_ASSERT(gFontDescTable, "no lookup table, needs addref"); 153 nsCSSFontDesc which = nsCSSFontDesc(gFontDescTable->Lookup(aFontDesc)); 154 155 return which; 156 } 157 158 static constexpr auto sDescNullStr = ""_ns; 159 160 const nsCString& nsCSSProps::GetStringValue(nsCSSFontDesc aFontDescID) { 161 MOZ_ASSERT(gFontDescTable, "no lookup table, needs addref"); 162 if (gFontDescTable) { 163 return gFontDescTable->GetStringValue(int32_t(aFontDescID)); 164 } 165 return sDescNullStr; 166 } 167 168 const nsCString& nsCSSProps::GetStringValue(nsCSSCounterDesc aCounterDescID) { 169 MOZ_ASSERT(gCounterDescTable, "no lookup table, needs addref"); 170 if (gCounterDescTable) { 171 return gCounterDescTable->GetStringValue(int32_t(aCounterDescID)); 172 } 173 return sDescNullStr; 174 } 175 176 CSSPropFlags nsCSSProps::PropFlags(NonCustomCSSPropertyId aProperty) { 177 MOZ_ASSERT(aProperty != eCSSProperty_UNKNOWN && 178 aProperty < eCSSProperty_COUNT_with_aliases, 179 "out of range"); 180 return kFlagsTable[aProperty]; 181 } 182 183 /* static */ 184 bool nsCSSProps::gPropertyEnabled[eCSSProperty_COUNT_with_aliases] = { 185 // If the property has any "ENABLED_IN" flag set, it is disabled by 186 // default. Note that, if a property has pref, whatever its default 187 // value is, it will later be changed in nsCSSProps::AddRefTable(). 188 // If the property has "ENABLED_IN" flags but doesn't have a pref, 189 // it is an internal property which is disabled elsewhere. 190 #define IS_ENABLED_BY_DEFAULT(flags_) \ 191 (!((flags_) & (CSSPropFlags::EnabledMask | CSSPropFlags::Inaccessible))) 192 193 #define CSS_PROP_LONGHAND(name_, id_, method_, flags_, ...) \ 194 IS_ENABLED_BY_DEFAULT(flags_), 195 #define CSS_PROP_SHORTHAND(name_, id_, method_, flags_, ...) \ 196 IS_ENABLED_BY_DEFAULT(flags_), 197 #define CSS_PROP_ALIAS(name_, aliasid_, id_, method_, flags_, ...) \ 198 IS_ENABLED_BY_DEFAULT(flags_), 199 #include "mozilla/ServoCSSPropList.h" 200 #undef CSS_PROP_ALIAS 201 #undef CSS_PROP_SHORTHAND 202 #undef CSS_PROP_LONGHAND 203 204 #undef IS_ENABLED_BY_DEFAULT 205 }; 206 207 /** 208 * A singleton class to register as a receiver for gfxVars. 209 * Updates the state of backdrop-filter's pref if the gfx 210 * backdrop filter var changes state. 211 */ 212 class nsCSSPropsGfxVarReceiver final : public gfx::gfxVarReceiver { 213 constexpr nsCSSPropsGfxVarReceiver() = default; 214 215 // Backdrop filter's last known enabled state. 216 static bool sLastKnownAllowBackdropFilter; 217 static nsCSSPropsGfxVarReceiver sInstance; 218 219 public: 220 static gfx::gfxVarReceiver& GetInstance() { return sInstance; } 221 222 void OnVarChanged(const nsTArray<gfx::GfxVarUpdate>&) override { 223 bool enabled = gfx::gfxVars::AllowBackdropFilter(); 224 if (sLastKnownAllowBackdropFilter != enabled) { 225 sLastKnownAllowBackdropFilter = enabled; 226 nsCSSProps::RecomputeEnabledState( 227 StaticPrefs::GetPrefName_layout_css_backdrop_filter_enabled()); 228 } 229 } 230 }; 231 232 /* static */ 233 nsCSSPropsGfxVarReceiver nsCSSPropsGfxVarReceiver::sInstance = 234 nsCSSPropsGfxVarReceiver(); 235 236 /* static */ 237 bool nsCSSPropsGfxVarReceiver::sLastKnownAllowBackdropFilter = true; 238 239 /* static */ 240 gfx::gfxVarReceiver& nsCSSProps::GfxVarReceiver() { 241 return nsCSSPropsGfxVarReceiver::GetInstance(); 242 } 243 244 #include "nsCSSPropsGenerated.inc"