Bug 1268749 part 2 - Make pseudo-classes able to present conditionally like properties. r=heycam
MozReview-Commit-ID: 6D3UPQGrS71
--- a/layout/inspector/inDOMUtils.cpp
+++ b/layout/inspector/inDOMUtils.cpp
@@ -1206,26 +1206,25 @@ GetStatesForPseudoClass(const nsAString&
EventStates(),
EventStates()
};
static_assert(MOZ_ARRAY_LENGTH(sPseudoClassStates) ==
static_cast<size_t>(CSSPseudoClassType::MAX),
"Length of PseudoClassStates array is incorrect");
nsCOMPtr<nsIAtom> atom = NS_Atomize(aStatePseudo);
+ CSSPseudoClassType type = nsCSSPseudoClasses::GetPseudoType(atom, true, true);
// Ignore :moz-any-link so we don't give the element simultaneous
// visited and unvisited style state
- if (nsCSSPseudoClasses::GetPseudoType(atom) ==
- CSSPseudoClassType::mozAnyLink) {
+ if (type == CSSPseudoClassType::mozAnyLink) {
return EventStates();
}
// Our array above is long enough that indexing into it with
// NotPseudo is ok.
- CSSPseudoClassType type = nsCSSPseudoClasses::GetPseudoType(atom);
return sPseudoClassStates[static_cast<CSSPseudoClassTypeBase>(type)];
}
NS_IMETHODIMP
inDOMUtils::GetCSSPseudoElementNames(uint32_t* aLength, char16_t*** aNames)
{
nsTArray<nsIAtom*> array;
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -5912,29 +5912,24 @@ CSSParserImpl::ParsePseudoSelector(int32
nsContentUtils::ASCIIToLower(buffer);
nsCOMPtr<nsIAtom> pseudo = NS_Atomize(buffer);
// stash away some info about this pseudo so we only have to get it once.
bool isTreePseudo = false;
CSSPseudoElementType pseudoElementType =
nsCSSPseudoElements::GetPseudoType(pseudo);
CSSPseudoClassType pseudoClassType =
- nsCSSPseudoClasses::GetPseudoType(pseudo);
+ nsCSSPseudoClasses::GetPseudoType(pseudo, AgentRulesEnabled(),
+ ChromeRulesEnabled());
bool pseudoClassIsUserAction =
nsCSSPseudoClasses::IsUserActionPseudoClass(pseudoClassType);
- if (!AgentRulesEnabled() &&
- ((pseudoElementType < CSSPseudoElementType::Count &&
- nsCSSPseudoElements::PseudoElementIsUASheetOnly(pseudoElementType)) ||
- (pseudoClassType != CSSPseudoClassType::NotPseudo &&
- nsCSSPseudoClasses::PseudoClassIsUASheetOnly(pseudoClassType)) ||
- (!ChromeRulesEnabled() &&
- (pseudoClassType != CSSPseudoClassType::NotPseudo &&
- nsCSSPseudoClasses::PseudoClassIsUASheetAndChromeOnly(pseudoClassType))))) {
- // This pseudo-element or pseudo-class is not exposed to content.
+ if (pseudoElementType < CSSPseudoElementType::Count && !AgentRulesEnabled() &&
+ nsCSSPseudoElements::PseudoElementIsUASheetOnly(pseudoElementType)) {
+ // This pseudo-element is not exposed to content.
REPORT_UNEXPECTED_TOKEN(PEPseudoSelUnknown);
UngetToken();
return eSelectorParsingStatus_Error;
}
if (nsCSSAnonBoxes::IsNonElement(pseudo)) {
// Non-element anonymous boxes should not match any rule.
REPORT_UNEXPECTED_TOKEN(PEPseudoSelUnknown);
--- a/layout/style/nsCSSPseudoClassList.h
+++ b/layout/style/nsCSSPseudoClassList.h
@@ -92,17 +92,17 @@ CSS_PSEUDO_CLASS(mozIsHTML, ":-moz-is-ht
// Match all custom elements whose created callback has not yet been invoked
CSS_STATE_PSEUDO_CLASS(unresolved, ":unresolved", 0, "", NS_EVENT_STATE_UNRESOLVED)
// Matches nodes that are in a native-anonymous subtree (i.e., nodes in
// a subtree of C++ anonymous content constructed by Gecko for its own
// purposes).
CSS_PSEUDO_CLASS(mozNativeAnonymous, ":-moz-native-anonymous",
- CSS_PSEUDO_CLASS_UA_SHEET_ONLY, "")
+ CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS, "")
// Matches anything when the specified look-and-feel metric is set
CSS_PSEUDO_CLASS(mozSystemMetric, ":-moz-system-metric", 0, "")
// -moz-locale-dir(ltr) and -moz-locale-dir(rtl) may be used
// to match based on the locale's chrome direction
CSS_PSEUDO_CLASS(mozLocaleDir, ":-moz-locale-dir", 0, "")
@@ -119,17 +119,17 @@ CSS_PSEUDO_CLASS(mozLWThemeDarkText, ":-
CSS_PSEUDO_CLASS(mozWindowInactive, ":-moz-window-inactive", 0, "")
// Matches any table elements that have a nonzero border attribute,
// according to HTML integer attribute parsing rules.
CSS_PSEUDO_CLASS(mozTableBorderNonzero, ":-moz-table-border-nonzero", 0, "")
// Matches HTML frame/iframe elements which are mozbrowser.
CSS_PSEUDO_CLASS(mozBrowserFrame, ":-moz-browser-frame",
- CSS_PSEUDO_CLASS_UA_SHEET_AND_CHROME, "")
+ CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME, "")
// Matches whatever the contextual reference elements are for the
// matching operation.
CSS_PSEUDO_CLASS(scope, ":scope", 0, "layout.css.scope-pseudo.enabled")
// :not needs to come at the end of the non-bit pseudo-class list, since
// it doesn't actually get directly matched on in SelectorMatches.
CSS_PSEUDO_CLASS(negation, ":not", 0, "")
@@ -171,44 +171,44 @@ CSS_STATE_PSEUDO_CLASS(mozFullScreenAnce
// Matches if the element is focused and should show a focus ring
CSS_STATE_PSEUDO_CLASS(mozFocusRing, ":-moz-focusring", 0, "", NS_EVENT_STATE_FOCUSRING)
// Image, object, etc state pseudo-classes
CSS_STATE_PSEUDO_CLASS(mozBroken, ":-moz-broken", 0, "", NS_EVENT_STATE_BROKEN)
CSS_STATE_PSEUDO_CLASS(mozLoading, ":-moz-loading", 0, "", NS_EVENT_STATE_LOADING)
CSS_STATE_PSEUDO_CLASS(mozUserDisabled, ":-moz-user-disabled",
- CSS_PSEUDO_CLASS_UA_SHEET_AND_CHROME, "",
+ CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME, "",
NS_EVENT_STATE_USERDISABLED)
CSS_STATE_PSEUDO_CLASS(mozSuppressed, ":-moz-suppressed",
- CSS_PSEUDO_CLASS_UA_SHEET_AND_CHROME, "",
+ CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME, "",
NS_EVENT_STATE_SUPPRESSED)
CSS_STATE_PSEUDO_CLASS(mozTypeUnsupported, ":-moz-type-unsupported",
- CSS_PSEUDO_CLASS_UA_SHEET_AND_CHROME, "",
+ CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME, "",
NS_EVENT_STATE_TYPE_UNSUPPORTED)
CSS_STATE_PSEUDO_CLASS(mozTypeUnsupportedPlatform, ":-moz-type-unsupported-platform",
- CSS_PSEUDO_CLASS_UA_SHEET_AND_CHROME, "",
+ CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME, "",
NS_EVENT_STATE_TYPE_UNSUPPORTED_PLATFORM)
CSS_STATE_PSEUDO_CLASS(mozHandlerClickToPlay, ":-moz-handler-clicktoplay",
- CSS_PSEUDO_CLASS_UA_SHEET_AND_CHROME, "",
+ CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME, "",
NS_EVENT_STATE_TYPE_CLICK_TO_PLAY)
CSS_STATE_PSEUDO_CLASS(mozHandlerVulnerableUpdatable, ":-moz-handler-vulnerable-updatable",
- CSS_PSEUDO_CLASS_UA_SHEET_AND_CHROME, "",
+ CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME, "",
NS_EVENT_STATE_VULNERABLE_UPDATABLE)
CSS_STATE_PSEUDO_CLASS(mozHandlerVulnerableNoUpdate, ":-moz-handler-vulnerable-no-update",
- CSS_PSEUDO_CLASS_UA_SHEET_AND_CHROME, "",
+ CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME, "",
NS_EVENT_STATE_VULNERABLE_NO_UPDATE)
CSS_STATE_PSEUDO_CLASS(mozHandlerDisabled, ":-moz-handler-disabled",
- CSS_PSEUDO_CLASS_UA_SHEET_AND_CHROME, "",
+ CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME, "",
NS_EVENT_STATE_HANDLER_DISABLED)
CSS_STATE_PSEUDO_CLASS(mozHandlerBlocked, ":-moz-handler-blocked",
- CSS_PSEUDO_CLASS_UA_SHEET_AND_CHROME, "",
+ CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME, "",
NS_EVENT_STATE_HANDLER_BLOCKED)
CSS_STATE_PSEUDO_CLASS(mozHandlerCrashed, ":-moz-handler-crashed",
- CSS_PSEUDO_CLASS_UA_SHEET_AND_CHROME, "",
+ CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME, "",
NS_EVENT_STATE_HANDLER_CRASHED)
CSS_STATE_PSEUDO_CLASS(mozMathIncrementScriptLevel,
":-moz-math-increment-script-level", 0, "",
NS_EVENT_STATE_INCREMENT_SCRIPT_LEVEL)
// CSS 3 UI
// http://www.w3.org/TR/2004/CR-css3-ui-20040511/#pseudo-classes
--- a/layout/style/nsCSSPseudoClasses.cpp
+++ b/layout/style/nsCSSPseudoClasses.cpp
@@ -20,16 +20,24 @@ using namespace mozilla;
#include "nsCSSPseudoClassList.h"
#undef CSS_PSEUDO_CLASS
#define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_) \
NS_STATIC_ATOM_BUFFER(name_##_pseudo_class_buffer, value_)
#include "nsCSSPseudoClassList.h"
#undef CSS_PSEUDO_CLASS
+#define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_) \
+ static_assert(!((flags_) & CSS_PSEUDO_CLASS_ENABLED_IN_CHROME) || \
+ ((flags_) & CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS), \
+ "Pseudo-class '" #name_ "' is enabled in chrome, so it " \
+ "should also be enabled in UA sheets");
+#include "nsCSSPseudoClassList.h"
+#undef CSS_PSEUDO_CLASS
+
// Array of nsStaticAtom for each of the pseudo-classes.
static const nsStaticAtom CSSPseudoClasses_info[] = {
#define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_) \
NS_STATIC_ATOM(name_##_pseudo_class_buffer, &sPseudoClass_##name_),
#include "nsCSSPseudoClassList.h"
#undef CSS_PSEUDO_CLASS
};
@@ -39,20 +47,28 @@ static const nsStaticAtom CSSPseudoClass
static const uint32_t CSSPseudoClasses_flags[] = {
#define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_) \
flags_,
#include "nsCSSPseudoClassList.h"
#undef CSS_PSEUDO_CLASS
};
static bool sPseudoClassEnabled[] = {
+// If the pseudo class has any "ENABLED_IN" flag set, it is disabled by
+// default. Note that, if a pseudo class has pref, whatever its default
+// value is, it'll later be changed in nsCSSPseudoClasses::AddRefAtoms()
+// If the pseudo class has "ENABLED_IN" flags but doesn't have a pref,
+// it is an internal pseudo class which is disabled elsewhere.
+#define IS_ENABLED_BY_DEFAULT(flags_) \
+ (!((flags_) & CSS_PSEUDO_CLASS_ENABLED_MASK))
#define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_) \
- true,
+ IS_ENABLED_BY_DEFAULT(flags_),
#include "nsCSSPseudoClassList.h"
#undef CSS_PSEUDO_CLASS
+#undef IS_ENABLED_BY_DEFAULT
};
void nsCSSPseudoClasses::AddRefAtoms()
{
NS_RegisterStaticAtoms(CSSPseudoClasses_info);
#define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_) \
if (pref_[0]) { \
@@ -85,22 +101,35 @@ nsCSSPseudoClasses::HasNthPairArg(Type a
void
nsCSSPseudoClasses::PseudoTypeToString(Type aType, nsAString& aString)
{
MOZ_ASSERT(aType < Type::Count, "Unexpected type");
auto idx = static_cast<CSSPseudoClassTypeBase>(aType);
(*CSSPseudoClasses_info[idx].mAtom)->ToString(aString);
}
-CSSPseudoClassType
-nsCSSPseudoClasses::GetPseudoType(nsIAtom* aAtom)
+/* static */ CSSPseudoClassType
+nsCSSPseudoClasses::GetPseudoType(nsIAtom* aAtom,
+ bool aAgentEnabled, bool aChromeEnabled)
{
for (uint32_t i = 0; i < ArrayLength(CSSPseudoClasses_info); ++i) {
if (*CSSPseudoClasses_info[i].mAtom == aAtom) {
- return sPseudoClassEnabled[i] ? Type(i) : Type::NotPseudo;
+ Type type = Type(i);
+ if (sPseudoClassEnabled[i]) {
+ return type;
+ } else {
+ auto flags = FlagsForPseudoClass(type);
+ if ((aChromeEnabled &&
+ (flags & CSS_PSEUDO_CLASS_ENABLED_IN_CHROME)) ||
+ (aAgentEnabled &&
+ (flags & CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS))) {
+ return type;
+ }
+ }
+ return Type::NotPseudo;
}
}
return Type::NotPseudo;
}
/* static */ bool
nsCSSPseudoClasses::IsUserActionPseudoClass(Type aType)
--- a/layout/style/nsCSSPseudoClasses.h
+++ b/layout/style/nsCSSPseudoClasses.h
@@ -5,20 +5,30 @@
/* atom list for CSS pseudo-classes */
#ifndef nsCSSPseudoClasses_h___
#define nsCSSPseudoClasses_h___
#include "nsStringFwd.h"
-// This pseudo-class is accepted only in UA style sheets.
-#define CSS_PSEUDO_CLASS_UA_SHEET_ONLY (1<<0)
-// This pseudo-class is accepted only in UA style sheets and chrome.
-#define CSS_PSEUDO_CLASS_UA_SHEET_AND_CHROME (1<<1)
+// The following two flags along with the pref defines where this pseudo
+// class can be used:
+// * If none of the two flags is presented, the pref completely controls
+// the availability of this pseudo class. And in that case, if it has
+// no pref, this property is usable everywhere.
+// * If any of the flags is set, this pseudo class is always enabled in
+// the specific contexts regardless of the value of the pref. If there
+// is no pref for this pseudo class at all in this case, it is an
+// internal-only pseudo class, which cannot be used anywhere else.
+#define CSS_PSEUDO_CLASS_ENABLED_MASK (3<<0)
+#define CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS (1<<0)
+#define CSS_PSEUDO_CLASS_ENABLED_IN_CHROME (1<<1)
+#define CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME \
+ (CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS | CSS_PSEUDO_CLASS_ENABLED_IN_CHROME)
class nsIAtom;
namespace mozilla {
// The total count of CSSPseudoClassType is less than 256,
// so use uint8_t as its underlying type.
typedef uint8_t CSSPseudoClassTypeBase;
@@ -37,37 +47,25 @@ enum class CSSPseudoClassType : CSSPseud
class nsCSSPseudoClasses
{
typedef mozilla::CSSPseudoClassType Type;
public:
static void AddRefAtoms();
- static Type GetPseudoType(nsIAtom* aAtom);
+ static Type GetPseudoType(nsIAtom* aAtom,
+ bool aAgentEnabled, bool aChromeEnabled);
static bool HasStringArg(Type aType);
static bool HasNthPairArg(Type aType);
static bool HasSelectorListArg(Type aType) {
return aType == Type::any;
}
static bool IsUserActionPseudoClass(Type aType);
- static bool PseudoClassIsUASheetOnly(Type aType) {
- return PseudoClassHasFlags(aType, CSS_PSEUDO_CLASS_UA_SHEET_ONLY);
- }
- static bool PseudoClassIsUASheetAndChromeOnly(Type aType) {
- return PseudoClassHasFlags(aType, CSS_PSEUDO_CLASS_UA_SHEET_AND_CHROME);
- }
-
// Should only be used on types other than Count and NotPseudoClass
static void PseudoTypeToString(Type aType, nsAString& aString);
private:
static uint32_t FlagsForPseudoClass(const Type aType);
-
- // Does the given pseudo-class have all of the flags given?
- static bool PseudoClassHasFlags(const Type aType, uint32_t aFlags)
- {
- return (FlagsForPseudoClass(aType) & aFlags) == aFlags;
- }
};
#endif /* nsCSSPseudoClasses_h___ */