blob: afdad99cf57de8000204359cd16f829fb4aa9757 [file] [log] [blame]
/*
* Copyright (C) 2014 Apple Inc. All rights reserved.
*
* 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.
*/
#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)
{
// 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.
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)
{
element->document().setContainsValidityStyleRules();
return element->isInRange();
}
ALWAYS_INLINE bool isOutOfRange(Element* element)
{
element->document().setContainsValidityStyleRules();
return element->isOutOfRange();
}
ALWAYS_INLINE bool isInvalid(const Element* element)
{
element->document().setContainsValidityStyleRules();
return element->willValidate() && !element->isValidFormControlElement();
}
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)
{
element->document().setContainsValidityStyleRules();
return element->willValidate() && element->isValidFormControlElement();
}
ALWAYS_INLINE bool isWindowInactive(const Element* element)
{
return !element->document().page()->focusController().isActive();
}
inline bool matchesLangPseudoClass(const Element* element, AtomicStringImpl* filter)
{
AtomicString value;
#if ENABLE(VIDEO_TRACK)
if (is<WebVTTElement>(*element))
value = downcast<WebVTTElement>(*element).language();
else
#endif
value = element->computeInheritedLanguage();
if (value.isNull())
return false;
if (value.impl() == filter)
return true;
if (value.impl()->startsWith(filter, false)) {
if (value.length() == filter->length())
return true;
return value[filter->length()] == '-';
}
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)
{
// 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 <iframe>, <object> or <embed> element whose child browsing
// context's Document is in the fullscreen state has the 'full-screen' pseudoclass applied.
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)
{
// While a Document is in the fullscreen state, the 'full-screen-document' pseudoclass applies
// to all elements of that Document.
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
} // namespace WebCore
#endif // SelectorCheckerTestFunctions_h