#pragma once
#include "CSSSelector.h"
#include "Element.h"
#include "StyleRelations.h"
namespace WebCore {
class CSSSelector;
class Element;
class RenderScrollbar;
class RenderStyle;
struct StyleScrollbarState {
ScrollbarPart scrollbarPart { NoPart };
ScrollbarPart hoveredPart { NoPart };
ScrollbarPart pressedPart { NoPart };
ScrollbarOrientation orientation { VerticalScrollbar };
ScrollbarButtonsPlacement buttonsPlacement { ScrollbarButtonsNone };
bool enabled { false };
bool scrollCornerIsVisible { false };
};
class SelectorChecker {
WTF_MAKE_NONCOPYABLE(SelectorChecker);
enum class Match { SelectorMatches, SelectorFailsLocally, SelectorFailsAllSiblings, SelectorFailsCompletely };
enum class MatchType { VirtualPseudoElementOnly, Element };
struct MatchResult {
Match match;
MatchType matchType;
static MatchResult matches(MatchType matchType)
{
return { Match::SelectorMatches, matchType };
}
static MatchResult updateWithMatchType(MatchResult result, MatchType matchType)
{
if (matchType == MatchType::VirtualPseudoElementOnly)
result.matchType = MatchType::VirtualPseudoElementOnly;
return result;
}
static MatchResult fails(Match match)
{
return { match, MatchType::Element };
}
};
public:
enum class Mode : unsigned char {
ResolvingStyle = 0, CollectingRules, CollectingRulesIgnoringVirtualPseudoElements, QueryingRules
};
SelectorChecker(Document&);
struct CheckingContext {
CheckingContext(SelectorChecker::Mode resolvingMode)
: resolvingMode(resolvingMode)
{ }
const SelectorChecker::Mode resolvingMode;
PseudoId pseudoId { PseudoId::None };
Optional<StyleScrollbarState> scrollbarState;
AtomString nameForHightlightPseudoElement;
const ContainerNode* scope { nullptr };
bool isMatchingHostPseudoClass { false };
const Element* shadowHostInPartRuleScope { nullptr };
Style::Relations styleRelations;
PseudoIdSet pseudoIDSet;
};
bool match(const CSSSelector&, const Element&, CheckingContext&) const;
bool matchHostPseudoClass(const CSSSelector&, const Element&, CheckingContext&) const;
static bool isCommonPseudoClassSelector(const CSSSelector*);
static bool attributeSelectorMatches(const Element&, const QualifiedName&, const AtomString& attributeValue, const CSSSelector&);
enum LinkMatchMask { MatchDefault = 0, MatchLink = 1, MatchVisited = 2, MatchAll = MatchLink | MatchVisited };
static unsigned determineLinkMatchType(const CSSSelector*);
struct LocalContext;
private:
MatchResult matchRecursively(CheckingContext&, const LocalContext&, PseudoIdSet&) const;
bool checkOne(CheckingContext&, const LocalContext&, MatchType&) const;
bool matchSelectorList(CheckingContext&, const LocalContext&, const Element&, const CSSSelectorList&) const;
bool checkScrollbarPseudoClass(const CheckingContext&, const Element&, const CSSSelector&) const;
bool m_strictParsing;
bool m_documentIsHTML;
};
inline bool SelectorChecker::isCommonPseudoClassSelector(const CSSSelector* selector)
{
if (selector->match() != CSSSelector::PseudoClass)
return false;
CSSSelector::PseudoClassType pseudoType = selector->pseudoClassType();
return pseudoType == CSSSelector::PseudoClassLink
|| pseudoType == CSSSelector::PseudoClassAnyLink
|| pseudoType == CSSSelector::PseudoClassAnyLinkDeprecated
|| pseudoType == CSSSelector::PseudoClassVisited
|| pseudoType == CSSSelector::PseudoClassFocus;
}
}