From 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c Mon Sep 17 00:00:00 2001 From: Lorry Tar Creator Date: Tue, 27 Jun 2017 06:07:23 +0000 Subject: webkitgtk-2.16.5 --- Source/WebCore/css/SelectorCheckerTestFunctions.h | 377 ++++++++++++++++++++++ 1 file changed, 377 insertions(+) create mode 100644 Source/WebCore/css/SelectorCheckerTestFunctions.h (limited to 'Source/WebCore/css/SelectorCheckerTestFunctions.h') diff --git a/Source/WebCore/css/SelectorCheckerTestFunctions.h b/Source/WebCore/css/SelectorCheckerTestFunctions.h new file mode 100644 index 000000000..db62a8b21 --- /dev/null +++ b/Source/WebCore/css/SelectorCheckerTestFunctions.h @@ -0,0 +1,377 @@ +/* + * Copyright (C) 2014-2016 Apple Inc. All rights reserved. + * Copyright (C) 2014 Dhi Aurrahman + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "FocusController.h" +#include "HTMLInputElement.h" +#include "HTMLOptionElement.h" +#include "RenderScrollbar.h" +#include "ScrollableArea.h" +#include "ScrollbarTheme.h" +#include + +#if ENABLE(VIDEO_TRACK) +#include "WebVTTElement.h" +#endif + +namespace WebCore { + +ALWAYS_INLINE bool isAutofilled(const Element& element) +{ + return is(element) && downcast(element).isAutoFilled(); +} + +ALWAYS_INLINE bool matchesDefaultPseudoClass(const Element& element) +{ + return element.matchesDefaultPseudoClass(); +} + +// https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled +ALWAYS_INLINE bool matchesDisabledPseudoClass(const Element& element) +{ + return is(element) && downcast(element).isActuallyDisabled(); +} + +// https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled +ALWAYS_INLINE bool matchesEnabledPseudoClass(const Element& element) +{ + return is(element) && downcast(element).canBeActuallyDisabled() && !element.isDisabledFormControl(); +} + +ALWAYS_INLINE bool isDefinedElement(const Element& element) +{ + return !element.isUndefinedCustomElement(); +} + +ALWAYS_INLINE bool isMediaDocument(const Element& element) +{ + return element.document().isMediaDocument(); +} + +ALWAYS_INLINE bool isChecked(const Element& element) +{ + // Even though WinIE allows checked and indeterminate to co-exist, the CSS selector spec says that + // you can't be both checked and indeterminate. We will behave like WinIE behind the scenes and just + // obey the CSS spec here in the test for matching the pseudo. + if (is(element)) { + auto& inputElement = downcast(element); + return inputElement.shouldAppearChecked() && !inputElement.shouldAppearIndeterminate(); + } + if (is(element)) + return const_cast(downcast(element)).selected(); + + return false; +} + +ALWAYS_INLINE bool isInRange(const Element& element) +{ + return element.isInRange(); +} + +ALWAYS_INLINE bool isOutOfRange(const 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) +{ + auto* page = element.document().page(); + if (!page) + return false; + return !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(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& argumentList) +{ + AtomicString language; +#if ENABLE(VIDEO_TRACK) + if (is(element)) + language = downcast(element).language(); + else +#endif + language = element.computeInheritedLanguage(); + + if (language.isEmpty()) + return false; + + // Implement basic and extended filterings of given language tags + // as specified in www.ietf.org/rfc/rfc4647.txt. + 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(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 matchesIndeterminatePseudoClass(const Element& element) +{ + return element.matchesIndeterminatePseudoClass(); +} + +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) +{ + // While a Document is in the fullscreen state, and the document's current fullscreen + // element is an element in the document, the 'full-screen' pseudoclass applies to + // that element. Also, an