// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "core/input/TouchEventManager.h"

#include "core/dom/Document.h"
#include "core/events/TouchEvent.h"
#include "core/frame/Deprecation.h"
#include "core/frame/EventHandlerRegistry.h"
#include "core/frame/FrameHost.h"
#include "core/frame/FrameView.h"
#include "core/html/HTMLCanvasElement.h"
#include "core/input/EventHandler.h"
#include "core/input/TouchActionUtil.h"
#include "core/page/ChromeClient.h"
#include "core/page/Page.h"
#include "platform/Histogram.h"
#include "platform/PlatformTouchEvent.h"
#include "wtf/CurrentTime.h"
#include "wtf/PtrUtil.h"
#include <memory>


namespace blink {

namespace {

bool hasTouchHandlers(const EventHandlerRegistry& registry)
{
    return registry.hasEventHandlers(EventHandlerRegistry::TouchStartOrMoveEventBlocking)
        || registry.hasEventHandlers(EventHandlerRegistry::TouchStartOrMoveEventPassive)
        || registry.hasEventHandlers(EventHandlerRegistry::TouchEndOrCancelEventBlocking)
        || registry.hasEventHandlers(EventHandlerRegistry::TouchEndOrCancelEventPassive);
}

const AtomicString& touchEventNameForTouchPointState(PlatformTouchPoint::TouchState state)
{
    switch (state) {
    case PlatformTouchPoint::TouchReleased:
        return EventTypeNames::touchend;
    case PlatformTouchPoint::TouchCancelled:
        return EventTypeNames::touchcancel;
    case PlatformTouchPoint::TouchPressed:
        return EventTypeNames::touchstart;
    case PlatformTouchPoint::TouchMoved:
        return EventTypeNames::touchmove;
    case PlatformTouchPoint::TouchStationary:
        // Fall through to default
    default:
        ASSERT_NOT_REACHED();
        return emptyAtom;
    }
}

enum TouchEventDispatchResultType {
    UnhandledTouches, // Unhandled touch events.
    HandledTouches, // Handled touch events.
    TouchEventDispatchResultTypeMax,
};

// Defining this class type local to dispatchTouchEvents() and annotating
// it with STACK_ALLOCATED(), runs into MSVC(VS 2013)'s C4822 warning
// that the local class doesn't provide a local definition for 'operator new'.
// Which it intentionally doesn't and shouldn't.
//
// Work around such toolchain bugginess by lifting out the type, thereby
// taking it out of C4822's reach.
class ChangedTouches final {
    STACK_ALLOCATED();
public:
    // The touches corresponding to the particular change state this struct
    // instance represents.
    Member<TouchList> m_touches;

    using EventTargetSet = HeapHashSet<Member<EventTarget>>;
    // Set of targets involved in m_touches.
    EventTargetSet m_targets;
};

} // namespace

TouchEventManager::TouchEventManager(LocalFrame* frame)
: m_frame(frame)
{
    clear();
}

TouchEventManager::~TouchEventManager()
{
}

WebInputEventResult TouchEventManager::dispatchTouchEvents(
    const PlatformTouchEvent& event,
    const HeapVector<TouchInfo>& touchInfos,
    bool allTouchesReleased)
{
    // Build up the lists to use for the |touches|, |targetTouches| and
    // |changedTouches| attributes in the JS event. See
    // http://www.w3.org/TR/touch-events/#touchevent-interface for how these
    // lists fit together.

    // Holds the complete set of touches on the screen.
    TouchList* touches = TouchList::create();

    // A different view on the 'touches' list above, filtered and grouped by
    // event target. Used for the |targetTouches| list in the JS event.
    using TargetTouchesHeapMap = HeapHashMap<EventTarget*, Member<TouchList>>;
    TargetTouchesHeapMap touchesByTarget;

    // Array of touches per state, used to assemble the |changedTouches| list.
    ChangedTouches changedTouches[PlatformTouchPoint::TouchStateEnd];

    for (unsigned i = 0; i < touchInfos.size(); ++i) {
        const TouchInfo& touchInfo = touchInfos[i];
        const PlatformTouchPoint& point = touchInfo.point;
        PlatformTouchPoint::TouchState pointState = point.state();

        Touch* touch = Touch::create(
            touchInfo.targetFrame.get(),
            touchInfo.touchNode.get(),
            point.id(),
            point.screenPos(),
            touchInfo.contentPoint,
            touchInfo.adjustedRadius,
            point.rotationAngle(),
            point.force(),
            touchInfo.region);

        // Ensure this target's touch list exists, even if it ends up empty, so
        // it can always be passed to TouchEvent::Create below.
        TargetTouchesHeapMap::iterator targetTouchesIterator = touchesByTarget.find(touchInfo.touchNode.get());
        if (targetTouchesIterator == touchesByTarget.end()) {
            touchesByTarget.set(touchInfo.touchNode.get(), TouchList::create());
            targetTouchesIterator = touchesByTarget.find(touchInfo.touchNode.get());
        }

        // |touches| and |targetTouches| should only contain information about
        // touches still on the screen, so if this point is released or
        // cancelled it will only appear in the |changedTouches| list.
        if (pointState != PlatformTouchPoint::TouchReleased && pointState != PlatformTouchPoint::TouchCancelled) {
            touches->append(touch);
            targetTouchesIterator->value->append(touch);
        }

        // Now build up the correct list for |changedTouches|.
        // Note that  any touches that are in the TouchStationary state (e.g. if
        // the user had several points touched but did not move them all) should
        // never be in the |changedTouches| list so we do not handle them
        // explicitly here. See https://bugs.webkit.org/show_bug.cgi?id=37609
        // for further discussion about the TouchStationary state.
        if (pointState != PlatformTouchPoint::TouchStationary && touchInfo.knownTarget) {
            ASSERT(pointState < PlatformTouchPoint::TouchStateEnd);
            if (!changedTouches[pointState].m_touches)
                changedTouches[pointState].m_touches = TouchList::create();
            changedTouches[pointState].m_touches->append(touch);
            changedTouches[pointState].m_targets.add(touchInfo.touchNode);
        }
    }

    if (allTouchesReleased) {
        m_touchSequenceDocument.clear();
        m_touchSequenceUserGestureToken.clear();
    }

    WebInputEventResult eventResult = WebInputEventResult::NotHandled;

    // Now iterate through the |changedTouches| list and |m_targets| within it,
    // sending TouchEvents to the targets as required.
    for (unsigned state = 0; state != PlatformTouchPoint::TouchStateEnd; ++state) {
        if (!changedTouches[state].m_touches)
            continue;

        const AtomicString& eventName(touchEventNameForTouchPointState(static_cast<PlatformTouchPoint::TouchState>(state)));
        for (const auto& eventTarget : changedTouches[state].m_targets) {
            EventTarget* touchEventTarget = eventTarget;
            TouchEvent* touchEvent = TouchEvent::create(
                touches, touchesByTarget.get(touchEventTarget), changedTouches[state].m_touches.get(),
                eventName, touchEventTarget->toNode()->document().domWindow(),
                event.getModifiers(), event.cancelable(), event.causesScrollingIfUncanceled(), event.touchStartOrFirstTouchMove(), event.timestamp());

            DispatchEventResult domDispatchResult = touchEventTarget->dispatchEvent(touchEvent);

            // Only report for top level documents with a single touch on
            // touch-start or the first touch-move.
            if (event.touchStartOrFirstTouchMove() && touchInfos.size() == 1 && m_frame->isMainFrame()) {

                // Record the disposition and latency of touch starts and first touch moves before and after the page is fully loaded respectively.
                int64_t latencyInMicros = static_cast<int64_t>((monotonicallyIncreasingTime() - event.timestamp()) * 1000000.0);
                if (event.cancelable()) {
                    if (m_frame->document()->isLoadCompleted()) {
                        DEFINE_STATIC_LOCAL(EnumerationHistogram, touchDispositionsAfterPageLoadHistogram, ("Event.Touch.TouchDispositionsAfterPageLoad", TouchEventDispatchResultTypeMax));
                        touchDispositionsAfterPageLoadHistogram.count((domDispatchResult != DispatchEventResult::NotCanceled) ? HandledTouches : UnhandledTouches);

                        DEFINE_STATIC_LOCAL(CustomCountHistogram, eventLatencyAfterPageLoadHistogram, ("Event.Touch.TouchLatencyAfterPageLoad", 1, 100000000, 50));
                        eventLatencyAfterPageLoadHistogram.count(latencyInMicros);
                    } else {
                        DEFINE_STATIC_LOCAL(EnumerationHistogram, touchDispositionsBeforePageLoadHistogram, ("Event.Touch.TouchDispositionsBeforePageLoad", TouchEventDispatchResultTypeMax));
                        touchDispositionsBeforePageLoadHistogram.count((domDispatchResult != DispatchEventResult::NotCanceled) ? HandledTouches : UnhandledTouches);

                        DEFINE_STATIC_LOCAL(CustomCountHistogram, eventLatencyBeforePageLoadHistogram, ("Event.Touch.TouchLatencyBeforePageLoad", 1, 100000000, 50));
                        eventLatencyBeforePageLoadHistogram.count(latencyInMicros);
                    }
                    // Report the touch disposition there is no active fling animation.
                    DEFINE_STATIC_LOCAL(EnumerationHistogram, touchDispositionsOutsideFlingHistogram, ("Event.Touch.TouchDispositionsOutsideFling2", TouchEventDispatchResultTypeMax));
                    touchDispositionsOutsideFlingHistogram.count((domDispatchResult != DispatchEventResult::NotCanceled) ? HandledTouches : UnhandledTouches);
                }

                // Report the touch disposition when there is an active fling animation.
                if (event.dispatchType() == PlatformEvent::ListenersForcedNonBlockingDueToFling) {
                    DEFINE_STATIC_LOCAL(EnumerationHistogram, touchDispositionsDuringFlingHistogram, ("Event.Touch.TouchDispositionsDuringFling2", TouchEventDispatchResultTypeMax));
                    touchDispositionsDuringFlingHistogram.count(touchEvent->preventDefaultCalledOnUncancelableEvent() ? HandledTouches : UnhandledTouches);
                }
            }
            eventResult = EventHandler::mergeEventResult(eventResult,
                EventHandler::toWebInputEventResult(domDispatchResult));
        }
    }

    if (allTouchesReleased)
        m_touchScrollStarted = false;

    return eventResult;
}

void TouchEventManager::updateTargetAndRegionMapsForTouchStarts(
    HeapVector<TouchInfo>& touchInfos)
{
    for (auto& touchInfo : touchInfos) {
        // Touch events implicitly capture to the touched node, and don't change
        // active/hover states themselves (Gesture events do). So we only need
        // to hit-test on touchstart and when the target could be different than
        // the corresponding pointer event target.
        if (touchInfo.point.state() == PlatformTouchPoint::TouchPressed) {
            HitTestRequest::HitTestRequestType hitType = HitTestRequest::TouchEvent | HitTestRequest::ReadOnly | HitTestRequest::Active;
            HitTestResult result;
            // For the touchPressed points hit-testing is done in
            // PointerEventManager. If it was the second touch there is a
            // capturing documents for the touch and |m_touchSequenceDocument|
            // is not null. So if PointerEventManager should hit-test again
            // against |m_touchSequenceDocument| if the target set by
            // PointerEventManager was either null or not in
            // |m_touchSequenceDocument|.
            if (m_touchSequenceDocument && (!touchInfo.touchNode
                || &touchInfo.touchNode->document() != m_touchSequenceDocument)) {
                if (m_touchSequenceDocument->frame()) {
                    LayoutPoint framePoint = roundedLayoutPoint(m_touchSequenceDocument->frame()->view()->rootFrameToContents(touchInfo.point.pos()));
                    result = EventHandler::hitTestResultInFrame(m_touchSequenceDocument->frame(), framePoint, hitType);
                    Node* node = result.innerNode();
                    if (!node)
                        continue;
                    if (isHTMLCanvasElement(node)) {
                        std::pair<Element*, String> regionInfo = toHTMLCanvasElement(node)->getControlAndIdIfHitRegionExists(result.pointInInnerNodeFrame());
                        if (regionInfo.first)
                            node = regionInfo.first;
                        touchInfo.region = regionInfo.second;
                    }
                    // Touch events should not go to text nodes.
                    if (node->isTextNode())
                        node = FlatTreeTraversal::parent(*node);
                    touchInfo.touchNode = node;
                } else {
                    continue;
                }
            }
            if (!touchInfo.touchNode)
                continue;
            if (!m_touchSequenceDocument) {
                // Keep track of which document should receive all touch events
                // in the active sequence. This must be a single document to
                // ensure we don't leak Nodes between documents.
                m_touchSequenceDocument = &(touchInfo.touchNode->document());
                ASSERT(m_touchSequenceDocument->frame()->view());
            }

            // Ideally we'd ASSERT(!m_targetForTouchID.contains(point.id())
            // since we shouldn't get a touchstart for a touch that's already
            // down. However EventSender allows this to be violated and there's
            // some tests that take advantage of it. There may also be edge
            // cases in the browser where this happens.
            // See http://crbug.com/345372.
            m_targetForTouchID.set(touchInfo.point.id(), touchInfo.touchNode);

            m_regionForTouchID.set(touchInfo.point.id(), touchInfo.region);

            TouchAction effectiveTouchAction =
                TouchActionUtil::computeEffectiveTouchAction(
                    *touchInfo.touchNode);
            if (effectiveTouchAction != TouchActionAuto)
                m_frame->page()->chromeClient().setTouchAction(effectiveTouchAction);
        }
    }
}

void TouchEventManager::setAllPropertiesOfTouchInfos(
    HeapVector<TouchInfo>& touchInfos)
{
    for (auto& touchInfo : touchInfos) {
        PlatformTouchPoint::TouchState pointState = touchInfo.point.state();
        Node* touchNode = nullptr;
        String regionID;

        if (pointState == PlatformTouchPoint::TouchReleased
            || pointState == PlatformTouchPoint::TouchCancelled) {
            // The target should be the original target for this touch, so get
            // it from the hashmap. As it's a release or cancel we also remove
            // it from the map.
            touchNode = m_targetForTouchID.take(touchInfo.point.id());
            regionID = m_regionForTouchID.take(touchInfo.point.id());
        } else {
            // No hittest is performed on move or stationary, since the target
            // is not allowed to change anyway.
            touchNode = m_targetForTouchID.get(touchInfo.point.id());
            regionID = m_regionForTouchID.get(touchInfo.point.id());
        }

        LocalFrame* targetFrame = nullptr;
        bool knownTarget = false;
        if (touchNode) {
            Document& doc = touchNode->document();
            // If the target node has moved to a new document while it was being touched,
            // we can't send events to the new document because that could leak nodes
            // from one document to another. See http://crbug.com/394339.
            if (&doc == m_touchSequenceDocument.get()) {
                targetFrame = doc.frame();
                knownTarget = true;
            }
        }
        if (!knownTarget) {
            // If we don't have a target registered for the point it means we've
            // missed our opportunity to do a hit test for it (due to some
            // optimization that prevented blink from ever seeing the
            // touchstart), or that the touch started outside the active touch
            // sequence document. We should still include the touch in the
            // Touches list reported to the application (eg. so it can
            // differentiate between a one and two finger gesture), but we won't
            // actually dispatch any events for it. Set the target to the
            // Document so that there's some valid node here. Perhaps this
            // should really be LocalDOMWindow, but in all other cases the target of
            // a Touch is a Node so using the window could be a breaking change.
            // Since we know there was no handler invoked, the specific target
            // should be completely irrelevant to the application.
            touchNode = m_touchSequenceDocument;
            targetFrame = m_touchSequenceDocument->frame();
        }
        ASSERT(targetFrame);

        // pagePoint should always be in the target element's document coordinates.
        FloatPoint pagePoint = targetFrame->view()->rootFrameToContents(
            touchInfo.point.pos());
        float scaleFactor = 1.0f / targetFrame->pageZoomFactor();

        touchInfo.touchNode = touchNode;
        touchInfo.targetFrame = targetFrame;
        touchInfo.contentPoint = pagePoint.scaledBy(scaleFactor);
        touchInfo.adjustedRadius = touchInfo.point.radius().scaledBy(scaleFactor);
        touchInfo.knownTarget = knownTarget;
        touchInfo.region = regionID;
    }
}

bool TouchEventManager::reHitTestTouchPointsIfNeeded(
    const PlatformTouchEvent& event,
    HeapVector<TouchInfo>& touchInfos)
{
    bool newTouchSequence = true;
    bool allTouchesReleased = true;

    for (const auto& point : event.touchPoints()) {
        if (point.state() != PlatformTouchPoint::TouchPressed)
            newTouchSequence = false;
        if (point.state() != PlatformTouchPoint::TouchReleased && point.state() != PlatformTouchPoint::TouchCancelled)
            allTouchesReleased = false;
    }
    if (newTouchSequence) {
        // Ideally we'd ASSERT(!m_touchSequenceDocument) here since we should
        // have cleared the active document when we saw the last release. But we
        // have some tests that violate this, ClusterFuzz could trigger it, and
        // there may be cases where the browser doesn't reliably release all
        // touches. http://crbug.com/345372 tracks this.
        m_touchSequenceDocument.clear();
        m_touchSequenceUserGestureToken.clear();
    }

    ASSERT(m_frame->view());
    if (m_touchSequenceDocument && (!m_touchSequenceDocument->frame() || !m_touchSequenceDocument->frame()->view())) {
        // If the active touch document has no frame or view, it's probably being destroyed
        // so we can't dispatch events.
        return false;
    }

    updateTargetAndRegionMapsForTouchStarts(touchInfos);

    m_touchPressed = !allTouchesReleased;

    // If there's no document receiving touch events, or no handlers on the
    // document set to receive the events, then we can skip all the rest of
    // this work.
    if (!m_touchSequenceDocument || !m_touchSequenceDocument->frameHost() || !hasTouchHandlers(m_touchSequenceDocument->frameHost()->eventHandlerRegistry()) || !m_touchSequenceDocument->frame()) {
        if (allTouchesReleased) {
            m_touchSequenceDocument.clear();
            m_touchSequenceUserGestureToken.clear();
        }
        return false;
    }

    setAllPropertiesOfTouchInfos(touchInfos);

    return true;
}

// TODO(rbyers): Replace with AutoReset as base/WTF unification permits.
class CurrentEventHolder {
    // Always stack allocated to ensure lifetime doesn't exceed that of target
    DISALLOW_NEW();
public:
    CurrentEventHolder(PlatformEvent::EventType& target, PlatformEvent::EventType value)
    : m_target(target)
    {
        m_target = value;
    }
    ~CurrentEventHolder()
    {
        m_target = PlatformEvent::NoType;
    }
private:
    PlatformEvent::EventType& m_target;
};

WebInputEventResult TouchEventManager::handleTouchEvent(
    const PlatformTouchEvent& event,
    HeapVector<TouchInfo>& touchInfos)
{
    // Track the current event for the scope of this function.
    CurrentEventHolder holder(m_currentEvent, event.type());

    if (!reHitTestTouchPointsIfNeeded(event, touchInfos))
        return WebInputEventResult::NotHandled;

    bool allTouchesReleased = true;
    for (const auto& point : event.touchPoints()) {
        if (point.state() != PlatformTouchPoint::TouchReleased
            && point.state() != PlatformTouchPoint::TouchCancelled)
            allTouchesReleased = false;
    }

    // Whether a touch should be considered a "user gesture" or not is a tricky question.
    // https://docs.google.com/document/d/1oF1T3O7_E4t1PYHV6gyCwHxOi3ystm0eSL5xZu7nvOg/edit#

    // The touchend corresponding to a tap is always a user gesture.
    bool isTap = event.touchPoints().size() == 1
        && event.touchPoints()[0].state() == PlatformTouchPoint::TouchReleased
        && !event.causesScrollingIfUncanceled();

    // For now, disallow dragging as a user gesture when the events are being sent to a
    // cross-origin iframe (crbug.com/582140).
    bool isSameOrigin = false;
    if (m_touchSequenceDocument && m_touchSequenceDocument->frame()) {
        SecurityOrigin* securityOrigin = m_touchSequenceDocument->frame()->securityContext()->getSecurityOrigin();
        Frame* top = m_frame->tree().top();
        if (top && securityOrigin->canAccess(top->securityContext()->getSecurityOrigin()))
            isSameOrigin = true;
    }

    std::unique_ptr<UserGestureIndicator> gestureIndicator;
    if (isTap || isSameOrigin) {
        UserGestureUtilizedCallback* callback = 0;
        // These are cases we'd like to migrate to not hold a user gesture.
        if (event.type() == PlatformEvent::TouchStart
            || event.type() == PlatformEvent::TouchMove
            || (event.type() == PlatformEvent::TouchEnd && m_touchScrollStarted)) {
            // Collect metrics in userGestureUtilized().
            callback = this;
        }
        if (m_touchSequenceUserGestureToken)
            gestureIndicator = wrapUnique(new UserGestureIndicator(m_touchSequenceUserGestureToken.release(), callback));
        else
            gestureIndicator = wrapUnique(new UserGestureIndicator(DefinitelyProcessingUserGesture, callback));
        m_touchSequenceUserGestureToken = UserGestureIndicator::currentToken();
    }

    return dispatchTouchEvents(event, touchInfos, allTouchesReleased);
}

void TouchEventManager::clear()
{
    m_touchSequenceDocument.clear();
    m_touchSequenceUserGestureToken.clear();
    m_targetForTouchID.clear();
    m_regionForTouchID.clear();
    m_touchPressed = false;
    m_touchScrollStarted = false;
    m_currentEvent = PlatformEvent::NoType;
}

bool TouchEventManager::isAnyTouchActive() const
{
    return m_touchPressed;
}

DEFINE_TRACE(TouchEventManager)
{
    visitor->trace(m_frame);
    visitor->trace(m_touchSequenceDocument);
    visitor->trace(m_targetForTouchID);
}

void TouchEventManager::userGestureUtilized()
{
    // This is invoked for UserGestureIndicators created in TouchEventManger::handleTouchEvent which perhaps
    // represent touch actions which shouldn't be considered a user-gesture.  Trigger a UseCounter based
    // on the touch event that's currently being dispatched.
    UseCounter::Feature feature;

    switch (m_currentEvent) {
    case PlatformEvent::TouchStart:
        feature = UseCounter::TouchStartUserGestureUtilized;
        break;
    case PlatformEvent::TouchMove:
        feature = UseCounter::TouchMoveUserGestureUtilized;
        break;
    case PlatformEvent::TouchEnd:
        feature = UseCounter::TouchEndDuringScrollUserGestureUtilized;
        break;
    default:
        NOTREACHED();
        return;
    }
    Deprecation::countDeprecation(m_frame, feature);
}

} // namespace blink
