/*
 * 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 PLATFORM(IOS_FAMILY)
#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;
}

enum class ElementHadRenderer { No, Yes };
static bool isConsideredClickable(const Element& candidateElement, ElementHadRenderer hadRenderer)
{
    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;
}

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()))
        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 << ").");

    // isConsideredClickable may trigger style update through Node::computeEditability. Let's adjust the state in the next runloop.
    callOnMainThread([weakThis = makeWeakPtr(*this), targetElement = makeWeakPtr(element)] {
        if (!weakThis || !targetElement)
            return;
        if (isVisuallyHidden(*targetElement)) {
            weakThis->adjustObservedState(Event::EndedTransitionButFinalStyleIsNotDefiniteYet);
            return;
        }
        if (isConsideredClickable(*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.hasValue())
        return;

    if (!isConsideredClickable(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 // PLATFORM(IOS_FAMILY)
