/*
 * Copyright (C) 2019 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.
 */

#include "config.h"
#include "ContentChangeObserver.h"

#if ENABLE(CONTENT_CHANGE_OBSERVER)
#include "Chrome.h"
#include "ChromeClient.h"
#include "DOMTimer.h"
#include "Document.h"
#include "FullscreenManager.h"
#include "HTMLIFrameElement.h"
#include "HTMLImageElement.h"
#include "Logging.h"
#include "NodeRenderStyle.h"
#include "Page.h"
#include "Quirks.h"
#include "RenderDescendantIterator.h"
#include "Settings.h"

namespace WebCore {

static const Seconds maximumDelayForTimers { 400_ms };
static const Seconds maximumDelayForTransitions { 300_ms };

#if ENABLE(FULLSCREEN_API)
static bool isHiddenBehindFullscreenElement(const Node& descendantCandidate)
{
    // Fullscreen status is propagated on the ancestor document chain all the way to the top document.
    auto& document = descendantCandidate.document();
    auto* topMostFullScreenElement = document.topDocument().fullscreenManager().fullscreenElement();
    if (!topMostFullScreenElement)
        return false;

    // If the document where the node lives does not have an active fullscreen element, it is a sibling/nephew document -> not a descendant.
    auto* fullscreenElement = document.fullscreenManager().fullscreenElement();
    if (!fullscreenElement)
        return true;
    return !descendantCandidate.isDescendantOf(*fullscreenElement);
}
#endif

bool ContentChangeObserver::isVisuallyHidden(const Node& node)
{
    if (!node.renderStyle())
        return true;

    auto& style = *node.renderStyle();
    if (style.display() == DisplayType::None)
        return true;

    if (style.visibility() == Visibility::Hidden)
        return true;

    if (!style.opacity())
        return true;

    auto width = style.logicalWidth();
    auto height = style.logicalHeight();
    if ((width.isFixed() && !width.value()) || (height.isFixed() && !height.value()))
        return true;

    auto top = style.logicalTop();
    auto left = style.logicalLeft();
    // FIXME: This is trying to check if the element is outside of the viewport. This is incorrect for many reasons.
    if (left.isFixed() && width.isFixed() && -left.value() >= width.value())
        return true;
    if (top.isFixed() && height.isFixed() && -top.value() >= height.value())
        return true;

    // It's a common technique used to position content offscreen.
    if (style.hasOutOfFlowPosition() && left.isFixed() && left.value() <= -999)
        return true;

    // FIXME: Check for other cases like zero height with overflow hidden.
    auto maxHeight = style.maxHeight();
    if (maxHeight.isFixed() && !maxHeight.value())
        return true;

    // Special case opacity, because a descendant with non-zero opacity should still be considered hidden when one of its ancetors has opacity: 0;
    // YouTube.com has this setup with the bottom control bar.
    constexpr static unsigned numberOfAncestorsToCheckForOpacity = 4;
    unsigned i = 0;
    for (auto* parent = node.parentNode(); parent && i < numberOfAncestorsToCheckForOpacity; parent = parent->parentNode(), ++i) {
        if (!parent->renderStyle() || !parent->renderStyle()->opacity())
            return true;
    }

#if ENABLE(FULLSCREEN_API)
    if (isHiddenBehindFullscreenElement(node))
        return true;
#endif
    return false;
}

bool ContentChangeObserver::isConsideredVisible(const Node& node)
{
    if (isVisuallyHidden(node))
        return false;

    auto& style = *node.renderStyle();
    auto width = style.logicalWidth();
    // 1px width or height content is not considered visible.
    if (width.isFixed() && width.value() <= 1)
        return false;

    auto height = style.logicalHeight();
    if (height.isFixed() && height.value() <= 1)
        return false;

    return true;
}

bool ContentChangeObserver::isConsideredActionableContent(const Element& candidateElement, ElementHadRenderer hadRenderer) const
{
    if (m_document.quirks().shouldTooltipPreventFromProceedingWithClick(candidateElement))
        return true;

    auto isConsideredClickable = [&] {
        auto& element = const_cast<Element&>(candidateElement);
        if (element.isInUserAgentShadowTree())
            return false;

        if (is<HTMLIFrameElement>(element))
            return true;

        if (is<HTMLImageElement>(element)) {
            // This is required to avoid HTMLImageElement's touch callout override logic. See rdar://problem/48937767.
            return element.Element::willRespondToMouseClickEvents();
        }
        bool hasRenderer = element.renderer();
        auto willRespondToMouseClickEvents = element.willRespondToMouseClickEvents();
        if (willRespondToMouseClickEvents || !hasRenderer || hadRenderer == ElementHadRenderer::No)
            return willRespondToMouseClickEvents;

        // In case when the content already had renderers it's not sufficient to check the candidate element only since it might just be the container for the clickable content.  
        for (auto& descendant : descendantsOfType<RenderElement>(*element.renderer())) {
            if (!descendant.element())
                continue;
            if (descendant.element()->willRespondToMouseClickEvents())
                return true;
        }
        return false;
    };
    return isConsideredClickable();
}

ContentChangeObserver::ContentChangeObserver(Document& document)
    : m_document(document)
    , m_contentObservationTimer([this] { completeDurationBasedContentObservation(); })
{
}

static void willNotProceedWithClick(Frame& mainFrame)
{
    for (auto* frame = &mainFrame; frame; frame = frame->tree().traverseNext()) {
        if (auto* document = frame->document())
            document->contentChangeObserver().willNotProceedWithClick();
    }
}

void ContentChangeObserver::didCancelPotentialTap(Frame& mainFrame)
{
    LOG(ContentObservation, "didCancelPotentialTap: cancel ongoing content change observing.");
    WebCore::willNotProceedWithClick(mainFrame);
}

void ContentChangeObserver::didRecognizeLongPress(Frame& mainFrame)
{
    LOG(ContentObservation, "didRecognizeLongPress: cancel ongoing content change observing.");
    WebCore::willNotProceedWithClick(mainFrame);
}

void ContentChangeObserver::didPreventDefaultForEvent(Frame& mainFrame)
{
    LOG(ContentObservation, "didPreventDefaultForEvent: cancel ongoing content change observing.");
    WebCore::willNotProceedWithClick(mainFrame);
}

void ContentChangeObserver::startContentObservationForDuration(Seconds duration)
{
    if (!m_document.settings().contentChangeObserverEnabled())
        return;
    ASSERT(!hasVisibleChangeState());
    LOG_WITH_STREAM(ContentObservation, stream << "startContentObservationForDuration: start observing the content for " << duration.milliseconds() << "ms");
    adjustObservedState(Event::StartedFixedObservationTimeWindow);
    m_contentObservationTimer.startOneShot(duration);
}

void ContentChangeObserver::completeDurationBasedContentObservation()
{
    LOG_WITH_STREAM(ContentObservation, stream << "completeDurationBasedContentObservation: complete duration based content observing ");
    adjustObservedState(Event::EndedFixedObservationTimeWindow);
}

void ContentChangeObserver::didAddTransition(const Element& element, const Animation& transition)
{
    if (!m_document.settings().contentChangeObserverEnabled())
        return;
    if (hasVisibleChangeState())
        return;
    if (!isObservingContentChanges())
        return;
    if (!isObservingTransitions())
        return;
    if (!transition.isDurationSet() || !transition.isPropertySet())
        return;
    if (!isObservedPropertyForTransition(transition.property().id))
        return;
    auto transitionEnd = Seconds { transition.duration() + std::max<double>(0, transition.isDelaySet() ? transition.delay() : 0) };
    if (transitionEnd > maximumDelayForTransitions)
        return;
    if (!isVisuallyHidden(element))
        return;
    // In case of multiple transitions, the first tranistion wins (and it has to produce a visible content change in order to show up as hover).
    if (m_elementsWithTransition.contains(&element))
        return;
    LOG_WITH_STREAM(ContentObservation, stream << "didAddTransition: transition created on " << &element << " (" << transitionEnd.milliseconds() << "ms).");

    m_elementsWithTransition.add(&element);
    adjustObservedState(Event::AddedTransition);
}

void ContentChangeObserver::didFinishTransition(const Element& element, CSSPropertyID propertyID)
{
    if (!isObservedPropertyForTransition(propertyID))
        return;
    if (!m_elementsWithTransition.take(&element))
        return;
    LOG_WITH_STREAM(ContentObservation, stream << "didFinishTransition: transition finished (" << &element << ").");

    // isConsideredActionableContent may trigger style update through Node::computeEditability. Let's adjust the state in the next runloop.
    callOnMainThread([weakThis = WeakPtr { *this }, targetElement = WeakPtr { element }] {
        if (!weakThis || !targetElement)
            return;
        if (isVisuallyHidden(*targetElement)) {
            weakThis->adjustObservedState(Event::EndedTransitionButFinalStyleIsNotDefiniteYet);
            return;
        }
        if (weakThis->isConsideredActionableContent(*targetElement, ElementHadRenderer::Yes))
            weakThis->elementDidBecomeVisible(*targetElement);
        weakThis->adjustObservedState(Event::CompletedTransition);
    });
}

void ContentChangeObserver::didRemoveTransition(const Element& element, CSSPropertyID propertyID)
{
    if (!isObservedPropertyForTransition(propertyID))
        return;
    if (!m_elementsWithTransition.take(&element))
        return;
    LOG_WITH_STREAM(ContentObservation, stream << "didRemoveTransition: transition got interrupted (" << &element << ").");

    adjustObservedState(Event::CanceledTransition);
}

void ContentChangeObserver::didInstallDOMTimer(const DOMTimer& timer, Seconds timeout, bool singleShot)
{
    if (!m_document.settings().contentChangeObserverEnabled())
        return;
    if (!isObservingContentChanges())
        return;
    if (!isObservingDOMTimerScheduling())
        return;
    if (hasVisibleChangeState())
        return;
    if (m_document.activeDOMObjectsAreSuspended())
        return;
    if (timeout > maximumDelayForTimers || !singleShot)
        return;
    LOG_WITH_STREAM(ContentObservation, stream << "didInstallDOMTimer: register this timer: (" << &timer << ") and observe when it fires.");

    registerDOMTimer(timer);
    adjustObservedState(Event::InstalledDOMTimer);
}

void ContentChangeObserver::didRemoveDOMTimer(const DOMTimer& timer)
{
    if (!containsObservedDOMTimer(timer))
        return;
    LOG_WITH_STREAM(ContentObservation, stream << "removeDOMTimer: remove registered timer (" << &timer << ")");

    unregisterDOMTimer(timer);
    adjustObservedState(Event::RemovedDOMTimer);
}

void ContentChangeObserver::willNotProceedWithClick()
{
    LOG(ContentObservation, "willNotProceedWithClick: click will not happen.");
    adjustObservedState(Event::WillNotProceedWithClick);
}

void ContentChangeObserver::domTimerExecuteDidStart(const DOMTimer& timer)
{
    if (!containsObservedDOMTimer(timer))
        return;
    LOG_WITH_STREAM(ContentObservation, stream << "startObservingDOMTimerExecute: start observing (" << &timer << ") timer callback.");

    m_observedDomTimerIsBeingExecuted = true;
    adjustObservedState(Event::StartedDOMTimerExecution);
}

void ContentChangeObserver::domTimerExecuteDidFinish(const DOMTimer& timer)
{
    if (!m_observedDomTimerIsBeingExecuted)
        return;
    LOG_WITH_STREAM(ContentObservation, stream << "stopObservingDOMTimerExecute: stop observing (" << &timer << ") timer callback.");

    m_observedDomTimerIsBeingExecuted = false;
    unregisterDOMTimer(timer);
    adjustObservedState(Event::EndedDOMTimerExecution);
}

void ContentChangeObserver::styleRecalcDidStart()
{
    if (!isWaitingForStyleRecalc())
        return;
    LOG(ContentObservation, "startObservingStyleRecalc: start observing style recalc.");

    m_isInObservedStyleRecalc = true;
    adjustObservedState(Event::StartedStyleRecalc);
}

void ContentChangeObserver::styleRecalcDidFinish()
{
    if (!m_isInObservedStyleRecalc)
        return;
    LOG(ContentObservation, "stopObservingStyleRecalc: stop observing style recalc");

    m_isInObservedStyleRecalc = false;
    adjustObservedState(Event::EndedStyleRecalc);
}

void ContentChangeObserver::stopObservingPendingActivities()
{
    setShouldObserveNextStyleRecalc(false);
    setShouldObserveDOMTimerSchedulingAndTransitions(false);
    clearObservedDOMTimers();
    clearObservedTransitions();
}

void ContentChangeObserver::stopContentObservation()
{
    reset();
}

void ContentChangeObserver::reset()
{
    stopObservingPendingActivities();
    setHasNoChangeState();

    setTouchEventIsBeingDispatched(false);
    setIsBetweenTouchEndAndMouseMoved(false);
    setMouseMovedEventIsBeingDispatched(false);

    m_isInObservedStyleRecalc = false;
    m_observedDomTimerIsBeingExecuted = false;

    m_visibilityCandidateList.clear();

    m_contentObservationTimer.stop();
    m_elementsWithDestroyedVisibleRenderer.clear();
    resetHiddenTouchTarget();
}

void ContentChangeObserver::didSuspendActiveDOMObjects()
{
    LOG(ContentObservation, "didSuspendActiveDOMObjects");
    reset();
}

void ContentChangeObserver::willDetachPage()
{
    LOG(ContentObservation, "willDetachPage");
    reset();
}

void ContentChangeObserver::rendererWillBeDestroyed(const Element& element)
{ 
    if (!m_document.settings().contentChangeObserverEnabled())
        return;
    if (!isObservingContentChanges())
        return;
    LOG_WITH_STREAM(ContentObservation, stream << "rendererWillBeDestroyed element: " << &element);

    if (!isVisuallyHidden(element))
        m_elementsWithDestroyedVisibleRenderer.add(&element);
    elementDidBecomeHidden(element);
}

void ContentChangeObserver::elementDidBecomeVisible(const Element& element)
{
    LOG_WITH_STREAM(ContentObservation, stream << "elementDidBecomeVisible: element went from hidden to visible: " << &element);
    m_visibilityCandidateList.add(element);
    adjustObservedState(Event::ElementDidBecomeVisible);
}

void ContentChangeObserver::elementDidBecomeHidden(const Element& element)
{
    LOG_WITH_STREAM(ContentObservation, stream << "elementDidBecomeHidden: element went from visible to hidden: " << &element);
    // Candidate element is no longer visible.
    if (!m_visibilityCandidateList.remove(element))
        return;
//    ASSERT(hasVisibleChangeState());
    if (m_visibilityCandidateList.computesEmpty())
        setHasIndeterminateState();
}

void ContentChangeObserver::touchEventDidStart(PlatformEvent::Type eventType)
{
#if ENABLE(TOUCH_EVENTS)
    if (!m_document.settings().contentChangeObserverEnabled() || m_document.quirks().shouldDisableContentChangeObserverTouchEventAdjustment())
        return;
    if (eventType != PlatformEvent::Type::TouchStart)
        return;
    LOG(ContentObservation, "touchEventDidStart: touch start event started.");
    setTouchEventIsBeingDispatched(true);
    adjustObservedState(Event::StartedTouchStartEventDispatching);
#else
    UNUSED_PARAM(eventType);
#endif
}

void ContentChangeObserver::touchEventDidFinish()
{
#if ENABLE(TOUCH_EVENTS)
    if (!isTouchEventBeingDispatched())
        return;
    ASSERT(m_document.settings().contentChangeObserverEnabled());
    LOG(ContentObservation, "touchEventDidFinish: touch start event finished.");
    setTouchEventIsBeingDispatched(false);
    adjustObservedState(Event::EndedTouchStartEventDispatching);
#endif
}

void ContentChangeObserver::mouseMovedDidStart()
{
    if (!m_document.settings().contentChangeObserverEnabled())
        return;
    LOG(ContentObservation, "mouseMovedDidStart: mouseMoved started.");
    setMouseMovedEventIsBeingDispatched(true);
    adjustObservedState(Event::StartedMouseMovedEventDispatching);
}

void ContentChangeObserver::mouseMovedDidFinish()
{
    if (!isMouseMovedEventBeingDispatched())
        return;
    ASSERT(m_document.settings().contentChangeObserverEnabled());
    LOG(ContentObservation, "mouseMovedDidFinish: mouseMoved finished.");
    adjustObservedState(Event::EndedMouseMovedEventDispatching);
    setMouseMovedEventIsBeingDispatched(false);
}

void ContentChangeObserver::willNotProceedWithFixedObservationTimeWindow()
{
    ASSERT(!isMouseMovedEventBeingDispatched());
    adjustObservedState(Event::WillNotProceedWithFixedObservationTimeWindow);
}

void ContentChangeObserver::setShouldObserveNextStyleRecalc(bool shouldObserve)
{
    if (shouldObserve)
        LOG(ContentObservation, "Wait until next style recalc fires.");
    m_isWaitingForStyleRecalc = shouldObserve;
}

void ContentChangeObserver::adjustObservedState(Event event)
{
    auto resetToStartObserving = [&] {
        setHasNoChangeState();
        clearObservedDOMTimers();
        clearObservedTransitions();
        setIsBetweenTouchEndAndMouseMoved(false);
        setShouldObserveNextStyleRecalc(false);
        setShouldObserveDOMTimerSchedulingAndTransitions(false);
        ASSERT(!m_isInObservedStyleRecalc);
        ASSERT(!m_observedDomTimerIsBeingExecuted);
    };

    auto notifyClientIfNeeded = [&] {
        if (isTouchEventBeingDispatched()) {
            LOG(ContentObservation, "notifyClientIfNeeded: Touch event is being dispatched. No need to notify the client.");
            return;
        }
        if (isBetweenTouchEndAndMouseMoved()) {
            LOG(ContentObservation, "notifyClientIfNeeded: Not reached mouseMoved yet. No need to notify the client.");
            return;
        }
        if (isMouseMovedEventBeingDispatched()) {
            LOG(ContentObservation, "notifyClientIfNeeded: in mouseMoved call. No need to notify the client.");
            return;
        }
        if (isObservationTimeWindowActive()) {
            LOG(ContentObservation, "notifyClientIfNeeded: Inside the fixed window observation. No need to notify the client.");
            return;
        }

        // The fixed observation window (which is the final step in content observation) is closed and now we check if are still waiting for timers or animations to finish.
        if (hasPendingActivity()) {
            LOG(ContentObservation, "notifyClientIfNeeded: We are still waiting on some events.");
            return;
        }

        // First demote to "no change" because we've got no pending activity anymore.
        if (observedContentChange() == WKContentIndeterminateChange)
            setHasNoChangeState();

        LOG_WITH_STREAM(ContentObservation, stream << "notifyClientIfNeeded: sending observedContentChange ->" << observedContentChange());
        ASSERT(m_document.page());
        ASSERT(m_document.frame());
        m_document.page()->chrome().client().didFinishContentChangeObserving(*m_document.frame(), observedContentChange());
        stopContentObservation();
    };

    // These user initiated events trigger content observation (touchStart and mouseMove). 
    {
        if (event == Event::StartedTouchStartEventDispatching) {
            resetToStartObserving();
            setShouldObserveDOMTimerSchedulingAndTransitions(true);
            return;
        }
        if (event == Event::EndedTouchStartEventDispatching) {
            setShouldObserveDOMTimerSchedulingAndTransitions(false);
            setIsBetweenTouchEndAndMouseMoved(true);
            return;
        }
        if (event == Event::StartedMouseMovedEventDispatching) {
            ASSERT(!m_document.hasPendingStyleRecalc());
            if (!isBetweenTouchEndAndMouseMoved())
                resetToStartObserving();
            setIsBetweenTouchEndAndMouseMoved(false);
            setShouldObserveDOMTimerSchedulingAndTransitions(!hasVisibleChangeState());
            return;
        }
        if (event == Event::EndedMouseMovedEventDispatching) {
            setShouldObserveDOMTimerSchedulingAndTransitions(false);
            return;
        }
    }
    // Fixed window observation starts soon after mouseMove when we don't have a definite answer to whether we should proceed with hover or click.
    {
        if (event == Event::StartedFixedObservationTimeWindow) {
            ASSERT(!hasVisibleChangeState());
            setHasIndeterminateState();
            return;
        }
        if (event == Event::EndedFixedObservationTimeWindow) {
            notifyClientIfNeeded();
            return;
        }
        if (event == Event::WillNotProceedWithFixedObservationTimeWindow) {
            notifyClientIfNeeded();
            return;
        }
    }
    // These events (DOM timer, transition and style recalc) could trigger style changes that are candidates to visibility checking.
    {
        if (event == Event::InstalledDOMTimer || event == Event::AddedTransition) {
            ASSERT(!hasVisibleChangeState());
            setHasIndeterminateState();
            return;
        }
        if (event == Event::RemovedDOMTimer || event == Event::CanceledTransition) {
            notifyClientIfNeeded();
            return;
        }
        if (event == Event::StartedDOMTimerExecution) {
            ASSERT(isObservationTimeWindowActive() || observedContentChange() == WKContentIndeterminateChange);
            return;
        }
        if (event == Event::EndedDOMTimerExecution) {
            if (m_document.hasPendingStyleRecalc()) {
                setShouldObserveNextStyleRecalc(true);
                return;
            }
            notifyClientIfNeeded();
            return;
        }
        if (event == Event::EndedTransitionButFinalStyleIsNotDefiniteYet) {
            // onAnimationEnd can be called while in the middle of resolving the document (synchronously) or
            // asynchronously right before the style update is issued. It also means we don't know whether this animation ends up producing visible content yet. 
            if (m_document.inStyleRecalc()) {
                // We need to start observing this style change synchronously.
                m_isInObservedStyleRecalc = true;
                return;
            }
            setShouldObserveNextStyleRecalc(true);
            return;
        }
        if (event == Event::CompletedTransition) {
            if (m_document.inStyleRecalc()) {
                m_isInObservedStyleRecalc = true;
                return;
            }
            notifyClientIfNeeded();
            return;
        }
        if (event == Event::StartedStyleRecalc) {
            setShouldObserveNextStyleRecalc(false);
            ASSERT(isObservationTimeWindowActive() || observedContentChange() == WKContentIndeterminateChange);
            return;
        }
        if (event == Event::EndedStyleRecalc) {
            notifyClientIfNeeded();
            return;
        }
    }
    // Either the page decided to call preventDefault on the touch action or the tap gesture evolved to some other gesture (long press, double tap). 
    if (event == Event::WillNotProceedWithClick) {
        stopContentObservation();
        return;
    }
    // The page produced an visible change on an actionable content.
    if (event == Event::ElementDidBecomeVisible) {
        setHasVisibleChangeState();
        // Stop pending activities. We don't need to observe them anymore.
        stopObservingPendingActivities();
        return;
    }
}

bool ContentChangeObserver::shouldObserveVisibilityChangeForElement(const Element& element)
{
    return isObservingContentChanges() && !visibleRendererWasDestroyed(element);
}

ContentChangeObserver::StyleChangeScope::StyleChangeScope(Document& document, const Element& element)
    : m_contentChangeObserver(document.contentChangeObserver())
    , m_element(element)
    , m_hadRenderer(element.renderer())
{
    if (m_contentChangeObserver.shouldObserveVisibilityChangeForElement(element))
        m_wasHidden = isVisuallyHidden(m_element);
}

ContentChangeObserver::StyleChangeScope::~StyleChangeScope()
{
    // Do we track this element?
    if (!m_wasHidden.has_value())
        return;

    if (!m_contentChangeObserver.isConsideredActionableContent(m_element, m_hadRenderer ? ElementHadRenderer::Yes : ElementHadRenderer::No))
        return;

    auto wasVisible = !m_wasHidden.value();
    auto isVisible = isConsideredVisible(m_element);
    if (!wasVisible && isVisible)
        m_contentChangeObserver.elementDidBecomeVisible(m_element);
    else if (wasVisible && !isVisible)
        m_contentChangeObserver.elementDidBecomeHidden(m_element);
}

#if ENABLE(TOUCH_EVENTS)
ContentChangeObserver::TouchEventScope::TouchEventScope(Document& document, PlatformEvent::Type eventType)
    : m_contentChangeObserver(document.contentChangeObserver())
{
    m_contentChangeObserver.touchEventDidStart(eventType);
}

ContentChangeObserver::TouchEventScope::~TouchEventScope()
{
    m_contentChangeObserver.touchEventDidFinish();
}
#endif

ContentChangeObserver::MouseMovedScope::MouseMovedScope(Document& document)
    : m_contentChangeObserver(document.contentChangeObserver())
{
    m_contentChangeObserver.mouseMovedDidStart();
}

ContentChangeObserver::MouseMovedScope::~MouseMovedScope()
{
    m_contentChangeObserver.mouseMovedDidFinish();
    m_contentChangeObserver.resetHiddenTouchTarget();
}

ContentChangeObserver::StyleRecalcScope::StyleRecalcScope(Document& document)
    : m_contentChangeObserver(document.contentChangeObserver())
{
    m_contentChangeObserver.styleRecalcDidStart();
}

ContentChangeObserver::StyleRecalcScope::~StyleRecalcScope()
{
    m_contentChangeObserver.styleRecalcDidFinish();
}

ContentChangeObserver::DOMTimerScope::DOMTimerScope(Document* document, const DOMTimer& domTimer)
    : m_contentChangeObserver(document ? &document->contentChangeObserver() : nullptr)
    , m_domTimer(domTimer)
{
    if (m_contentChangeObserver)
        m_contentChangeObserver->domTimerExecuteDidStart(m_domTimer);
}

ContentChangeObserver::DOMTimerScope::~DOMTimerScope()
{
    if (m_contentChangeObserver)
        m_contentChangeObserver->domTimerExecuteDidFinish(m_domTimer);
}

}

#endif // ENABLE(CONTENT_CHANGE_OBSERVER)
