SelectorCheckerTestFunctions.h [plain text]
#ifndef SelectorCheckerTestFunctions_h
#define SelectorCheckerTestFunctions_h
#include "FocusController.h"
#include "HTMLInputElement.h"
#include "HTMLOptionElement.h"
#include "RenderScrollbar.h"
#include "ScrollableArea.h"
#include "ScrollbarTheme.h"
#include <wtf/Compiler.h>
#if ENABLE(VIDEO_TRACK)
#include "WebVTTElement.h"
#endif
namespace WebCore {
ALWAYS_INLINE bool isAutofilled(const Element* element)
{
if (is<HTMLFormControlElement>(*element)) {
if (const HTMLInputElement* inputElement = element->toInputElement())
return inputElement->isAutoFilled();
}
return false;
}
ALWAYS_INLINE bool isDefaultButtonForForm(const Element* element)
{
return element->isDefaultButtonForForm();
}
ALWAYS_INLINE bool isDisabled(const Element* element)
{
return (is<HTMLFormControlElement>(*element) || is<HTMLOptionElement>(*element) || is<HTMLOptGroupElement>(*element))
&& element->isDisabledFormControl();
}
ALWAYS_INLINE bool isEnabled(const Element* element)
{
return (is<HTMLFormControlElement>(*element) || is<HTMLOptionElement>(*element) || is<HTMLOptGroupElement>(*element))
&& !element->isDisabledFormControl();
}
ALWAYS_INLINE bool isMediaDocument(Element* element)
{
return element->document().isMediaDocument();
}
ALWAYS_INLINE bool isChecked(Element* element)
{
const HTMLInputElement* inputElement = element->toInputElement();
if (inputElement && inputElement->shouldAppearChecked() && !inputElement->shouldAppearIndeterminate())
return true;
if (is<HTMLOptionElement>(*element) && downcast<HTMLOptionElement>(*element).selected())
return true;
return false;
}
ALWAYS_INLINE bool isInRange(Element* element)
{
return element->isInRange();
}
ALWAYS_INLINE bool isOutOfRange(Element* element)
{
return element->isOutOfRange();
}
ALWAYS_INLINE bool isInvalid(const Element* element)
{
return element->matchesInvalidPseudoClass();
}
ALWAYS_INLINE bool isOptionalFormControl(const Element* element)
{
return element->isOptionalFormControl();
}
ALWAYS_INLINE bool isRequiredFormControl(const Element* element)
{
return element->isRequiredFormControl();
}
ALWAYS_INLINE bool isValid(const Element* element)
{
return element->matchesValidPseudoClass();
}
ALWAYS_INLINE bool isWindowInactive(const Element* element)
{
return !element->document().page()->focusController().isActive();
}
ALWAYS_INLINE bool containslanguageSubtagMatchingRange(StringView language, StringView range, unsigned languageLength, unsigned& position)
{
unsigned languageSubtagsStartIndex = position;
unsigned languageSubtagsEndIndex = languageLength;
bool isAsteriskRange = range == "*";
do {
if (languageSubtagsStartIndex > 0)
languageSubtagsStartIndex += 1;
languageSubtagsEndIndex = std::min<unsigned>(language.find('-', languageSubtagsStartIndex), languageLength);
if (languageSubtagsStartIndex > languageSubtagsEndIndex)
return false;
StringView languageSubtag = language.substring(languageSubtagsStartIndex, languageSubtagsEndIndex - languageSubtagsStartIndex);
bool isEqual = equalIgnoringASCIICase(range, languageSubtag);
if (!isAsteriskRange) {
if ((!isEqual && !languageSubtagsStartIndex) || (languageSubtag.length() == 1 && languageSubtagsStartIndex > 0))
return false;
}
languageSubtagsStartIndex = languageSubtagsEndIndex;
if (isEqual || isAsteriskRange) {
position = languageSubtagsStartIndex;
return true;
}
} while (languageSubtagsStartIndex < languageLength);
return false;
}
ALWAYS_INLINE bool matchesLangPseudoClass(const Element* element, const Vector<AtomicString>& argumentList)
{
ASSERT(element);
AtomicString language;
#if ENABLE(VIDEO_TRACK)
if (is<WebVTTElement>(*element))
language = downcast<WebVTTElement>(*element).language();
else
#endif
language = element->computeInheritedLanguage();
if (language.isEmpty())
return false;
StringView languageStringView = language.string();
unsigned languageLength = language.length();
for (const AtomicString& range : argumentList) {
if (range.isEmpty())
continue;
if (range == "*")
return true;
StringView rangeStringView = range.string();
if (equalIgnoringASCIICase(languageStringView, rangeStringView) && !languageStringView.contains('-'))
return true;
unsigned rangeLength = rangeStringView.length();
unsigned rangeSubtagsStartIndex = 0;
unsigned rangeSubtagsEndIndex = rangeLength;
unsigned lastMatchedLanguageSubtagIndex = 0;
bool matchedRange = true;
do {
if (rangeSubtagsStartIndex > 0)
rangeSubtagsStartIndex += 1;
if (rangeSubtagsStartIndex > languageLength)
return false;
rangeSubtagsEndIndex = std::min<unsigned>(rangeStringView.find('-', rangeSubtagsStartIndex), rangeLength);
StringView rangeSubtag = rangeStringView.substring(rangeSubtagsStartIndex, rangeSubtagsEndIndex - rangeSubtagsStartIndex);
if (!containslanguageSubtagMatchingRange(languageStringView, rangeSubtag, languageLength, lastMatchedLanguageSubtagIndex)) {
matchedRange = false;
break;
}
rangeSubtagsStartIndex = rangeSubtagsEndIndex;
} while (rangeSubtagsStartIndex < rangeLength);
if (matchedRange)
return true;
}
return false;
}
ALWAYS_INLINE bool matchesReadOnlyPseudoClass(const Element* element)
{
return !element->matchesReadWritePseudoClass();
}
ALWAYS_INLINE bool matchesReadWritePseudoClass(const Element* element)
{
return element->matchesReadWritePseudoClass();
}
ALWAYS_INLINE bool shouldAppearIndeterminate(const Element* element)
{
return element->shouldAppearIndeterminate();
}
ALWAYS_INLINE bool scrollbarMatchesEnabledPseudoClass(const SelectorChecker::CheckingContext& context)
{
return context.scrollbar && context.scrollbar->enabled();
}
ALWAYS_INLINE bool scrollbarMatchesDisabledPseudoClass(const SelectorChecker::CheckingContext& context)
{
return context.scrollbar && !context.scrollbar->enabled();
}
ALWAYS_INLINE bool scrollbarMatchesHoverPseudoClass(const SelectorChecker::CheckingContext& context)
{
if (!context.scrollbar)
return false;
ScrollbarPart hoveredPart = context.scrollbar->hoveredPart();
if (context.scrollbarPart == ScrollbarBGPart)
return hoveredPart != NoPart;
if (context.scrollbarPart == TrackBGPart)
return hoveredPart == BackTrackPart || hoveredPart == ForwardTrackPart || hoveredPart == ThumbPart;
return context.scrollbarPart == hoveredPart;
}
ALWAYS_INLINE bool scrollbarMatchesActivePseudoClass(const SelectorChecker::CheckingContext& context)
{
if (!context.scrollbar)
return false;
ScrollbarPart pressedPart = context.scrollbar->pressedPart();
if (context.scrollbarPart == ScrollbarBGPart)
return pressedPart != NoPart;
if (context.scrollbarPart == TrackBGPart)
return pressedPart == BackTrackPart || pressedPart == ForwardTrackPart || pressedPart == ThumbPart;
return context.scrollbarPart == pressedPart;
}
ALWAYS_INLINE bool scrollbarMatchesHorizontalPseudoClass(const SelectorChecker::CheckingContext& context)
{
return context.scrollbar && context.scrollbar->orientation() == HorizontalScrollbar;
}
ALWAYS_INLINE bool scrollbarMatchesVerticalPseudoClass(const SelectorChecker::CheckingContext& context)
{
return context.scrollbar && context.scrollbar->orientation() == VerticalScrollbar;
}
ALWAYS_INLINE bool scrollbarMatchesDecrementPseudoClass(const SelectorChecker::CheckingContext& context)
{
return context.scrollbarPart == BackButtonStartPart || context.scrollbarPart == BackButtonEndPart || context.scrollbarPart == BackTrackPart;
}
ALWAYS_INLINE bool scrollbarMatchesIncrementPseudoClass(const SelectorChecker::CheckingContext& context)
{
return context.scrollbarPart == ForwardButtonStartPart || context.scrollbarPart == ForwardButtonEndPart || context.scrollbarPart == ForwardTrackPart;
}
ALWAYS_INLINE bool scrollbarMatchesStartPseudoClass(const SelectorChecker::CheckingContext& context)
{
return context.scrollbarPart == BackButtonStartPart || context.scrollbarPart == ForwardButtonStartPart || context.scrollbarPart == BackTrackPart;
}
ALWAYS_INLINE bool scrollbarMatchesEndPseudoClass(const SelectorChecker::CheckingContext& context)
{
return context.scrollbarPart == BackButtonEndPart || context.scrollbarPart == ForwardButtonEndPart || context.scrollbarPart == ForwardTrackPart;
}
ALWAYS_INLINE bool scrollbarMatchesDoubleButtonPseudoClass(const SelectorChecker::CheckingContext& context)
{
if (!context.scrollbar)
return false;
ScrollbarButtonsPlacement buttonsPlacement = context.scrollbar->theme()->buttonsPlacement();
if (context.scrollbarPart == BackButtonStartPart || context.scrollbarPart == ForwardButtonStartPart || context.scrollbarPart == BackTrackPart)
return buttonsPlacement == ScrollbarButtonsDoubleStart || buttonsPlacement == ScrollbarButtonsDoubleBoth;
if (context.scrollbarPart == BackButtonEndPart || context.scrollbarPart == ForwardButtonEndPart || context.scrollbarPart == ForwardTrackPart)
return buttonsPlacement == ScrollbarButtonsDoubleEnd || buttonsPlacement == ScrollbarButtonsDoubleBoth;
return false;
}
ALWAYS_INLINE bool scrollbarMatchesSingleButtonPseudoClass(const SelectorChecker::CheckingContext& context)
{
if (!context.scrollbar)
return false;
ScrollbarButtonsPlacement buttonsPlacement = context.scrollbar->theme()->buttonsPlacement();
if (context.scrollbarPart == BackButtonStartPart || context.scrollbarPart == ForwardButtonEndPart || context.scrollbarPart == BackTrackPart || context.scrollbarPart == ForwardTrackPart)
return buttonsPlacement == ScrollbarButtonsSingle;
return false;
}
ALWAYS_INLINE bool scrollbarMatchesNoButtonPseudoClass(const SelectorChecker::CheckingContext& context)
{
if (!context.scrollbar)
return false;
ScrollbarButtonsPlacement buttonsPlacement = context.scrollbar->theme()->buttonsPlacement();
if (context.scrollbarPart == BackTrackPart)
return buttonsPlacement == ScrollbarButtonsNone || buttonsPlacement == ScrollbarButtonsDoubleEnd;
if (context.scrollbarPart == ForwardTrackPart)
return buttonsPlacement == ScrollbarButtonsNone || buttonsPlacement == ScrollbarButtonsDoubleStart;
return false;
}
ALWAYS_INLINE bool scrollbarMatchesCornerPresentPseudoClass(const SelectorChecker::CheckingContext& context)
{
return context.scrollbar && context.scrollbar->scrollableArea().isScrollCornerVisible();
}
#if ENABLE(FULLSCREEN_API)
ALWAYS_INLINE bool matchesFullScreenPseudoClass(const Element* element)
{
if (element->isFrameElementBase() && element->containsFullScreenElement())
return true;
if (!element->document().webkitIsFullScreen())
return false;
return element == element->document().webkitCurrentFullScreenElement();
}
ALWAYS_INLINE bool matchesFullScreenAnimatingFullScreenTransitionPseudoClass(const Element* element)
{
if (element != element->document().webkitCurrentFullScreenElement())
return false;
return element->document().isAnimatingFullScreen();
}
ALWAYS_INLINE bool matchesFullScreenAncestorPseudoClass(const Element* element)
{
return element->containsFullScreenElement();
}
ALWAYS_INLINE bool matchesFullScreenDocumentPseudoClass(const Element* element)
{
if (!element->document().webkitIsFullScreen())
return false;
return true;
}
#endif
#if ENABLE(VIDEO_TRACK)
ALWAYS_INLINE bool matchesFutureCuePseudoClass(const Element* element)
{
return is<WebVTTElement>(*element) && !downcast<WebVTTElement>(*element).isPastNode();
}
ALWAYS_INLINE bool matchesPastCuePseudoClass(const Element* element)
{
return is<WebVTTElement>(*element) && downcast<WebVTTElement>(*element).isPastNode();
}
#endif
}
#endif // SelectorCheckerTestFunctions_h