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 /* atom list for CSS pseudo-classes */
8 
9 #ifndef nsCSSPseudoClasses_h___
10 #define nsCSSPseudoClasses_h___
11 
12 #include "nsStringFwd.h"
13 #include "mozilla/CSSEnabledState.h"
14 #include "mozilla/EventStates.h"
15 #include "mozilla/Maybe.h"
16 
17 // The following two flags along with the pref defines where this pseudo
18 // class can be used:
19 // * If none of the two flags is presented, the pref completely controls
20 //   the availability of this pseudo class. And in that case, if it has
21 //   no pref, this property is usable everywhere.
22 // * If any of the flags is set, this pseudo class is always enabled in
23 //   the specific contexts regardless of the value of the pref. If there
24 //   is no pref for this pseudo class at all in this case, it is an
25 //   internal-only pseudo class, which cannot be used anywhere else.
26 #define CSS_PSEUDO_CLASS_ENABLED_MASK (3 << 0)
27 #define CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS (1 << 0)
28 #define CSS_PSEUDO_CLASS_ENABLED_IN_CHROME (1 << 1)
29 #define CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME \
30   (CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS | CSS_PSEUDO_CLASS_ENABLED_IN_CHROME)
31 
32 class nsAtom;
33 class nsIDocument;
34 
35 namespace mozilla {
36 namespace dom {
37 class Element;
38 }  // namespace dom
39 
40 // The total count of CSSPseudoClassType is less than 256,
41 // so use uint8_t as its underlying type.
42 typedef uint8_t CSSPseudoClassTypeBase;
43 enum class CSSPseudoClassType : CSSPseudoClassTypeBase {
44 #define CSS_PSEUDO_CLASS(_name, _value, _flags, _pref) _name,
45 #include "nsCSSPseudoClassList.h"
46 #undef CSS_PSEUDO_CLASS
47   Count,
48   NotPseudo,  // This value MUST be second last! SelectorMatches depends on it.
49   MAX
50 };
51 
52 }  // namespace mozilla
53 
54 class nsCSSPseudoClasses {
55   typedef mozilla::CSSPseudoClassType Type;
56   typedef mozilla::CSSEnabledState EnabledState;
57 
58  public:
59   static void AddRefAtoms();
60 
61   static Type GetPseudoType(nsAtom* aAtom, EnabledState aEnabledState);
62   static bool HasStringArg(Type aType);
63   static bool HasNthPairArg(Type aType);
HasSelectorListArg(Type aType)64   static bool HasSelectorListArg(Type aType) { return aType == Type::any; }
65   static bool IsUserActionPseudoClass(Type aType);
66 
67   // Should only be used on types other than Count and NotPseudoClass
68   static void PseudoTypeToString(Type aType, nsAString& aString);
69 
IsEnabled(Type aType,EnabledState aEnabledState)70   static bool IsEnabled(Type aType, EnabledState aEnabledState) {
71     auto index = static_cast<size_t>(aType);
72     MOZ_ASSERT(index < static_cast<size_t>(Type::Count));
73     if (sPseudoClassEnabled[index] ||
74         aEnabledState == EnabledState::eIgnoreEnabledState) {
75       return true;
76     }
77     auto flags = kPseudoClassFlags[index];
78     if (((aEnabledState & EnabledState::eInChrome) &&
79          (flags & CSS_PSEUDO_CLASS_ENABLED_IN_CHROME)) ||
80         ((aEnabledState & EnabledState::eInUASheets) &&
81          (flags & CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS))) {
82       return true;
83     }
84     return false;
85   }
86 
87   // Checks whether the given pseudo class matches the element.
88   // It returns Some(result) if this function is able to check
89   // the pseudo-class, Nothing() otherwise.
90   static mozilla::Maybe<bool> MatchesElement(
91       Type aType, const mozilla::dom::Element* aElement);
92 
93   /**
94    * Checks if a function-like ident-containing pseudo (:pseudo(ident))
95    * matches a given element.
96    *
97    * Returns true if it parses and matches, Some(false) if it
98    * parses but does not match. Asserts if it fails to parse; only
99    * call this when you're sure it's a string-like pseudo.
100    *
101    * In Servo mode, please ensure that UpdatePossiblyStaleDocumentState()
102    * has been called first.
103    *
104    * @param aElement The element we are trying to match
105    * @param aPseudo The name of the pseudoselector
106    * @param aString The identifier inside the pseudoselector (cannot be null)
107    * @param aDocument The document
108    * @param aStateMask Mask containing states which we should exclude.
109    *                   Ignored if aDependence is null
110    * @param aDependence Pointer to be set to true if we ignored a state due to
111    *                    aStateMask. Can be null.
112    */
113   static bool StringPseudoMatches(const mozilla::dom::Element* aElement,
114                                   mozilla::CSSPseudoClassType aPseudo,
115                                   const char16_t* aString,
116                                   const nsIDocument* aDocument,
117                                   mozilla::EventStates aStateMask,
118                                   bool* const aDependence = nullptr);
119 
120   static bool LangPseudoMatches(const mozilla::dom::Element* aElement,
121                                 const nsAtom* aOverrideLang,
122                                 bool aHasOverrideLang, const char16_t* aString,
123                                 const nsIDocument* aDocument);
124 
125   static const mozilla::EventStates
126       sPseudoClassStateDependences[size_t(Type::Count) + 2];
127 
128  private:
129   static const uint32_t kPseudoClassFlags[size_t(Type::Count)];
130   static bool sPseudoClassEnabled[size_t(Type::Count)];
131 };
132 
133 #endif /* nsCSSPseudoClasses_h___ */
134