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

#include "components/input/passthrough_touch_event_queue.h"

#include <memory>
#include <string>
#include <utility>

#include "base/auto_reset.h"
#include "base/feature_list.h"
#include "base/metrics/field_trial_params.h"
#include "base/task/sequenced_task_runner.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/typed_macros.h"
#include "components/input/touch_timeout_handler.h"
#include "components/input/web_touch_event_traits.h"
#include "third_party/blink/public/common/features.h"
#include "ui/events/base_event_utils.h"
#include "ui/gfx/geometry/point_f.h"

using blink::WebInputEvent;
using blink::WebTouchEvent;
using blink::WebTouchPoint;
using ui::LatencyInfo;

namespace input {
namespace {

// Compare all properties of touch points to determine the state.
bool HasPointChanged(const WebTouchPoint& point_1,
                     const WebTouchPoint& point_2) {
  DCHECK_EQ(point_1.id, point_2.id);
  if (point_1.PositionInScreen() != point_2.PositionInScreen() ||
      point_1.PositionInWidget() != point_2.PositionInWidget() ||
      point_1.radius_x != point_2.radius_x ||
      point_1.radius_y != point_2.radius_y ||
      point_1.rotation_angle != point_2.rotation_angle ||
      point_1.force != point_2.force || point_1.tilt_x != point_2.tilt_x ||
      point_1.tilt_y != point_2.tilt_y) {
    return true;
  }
  return false;
}

}  // namespace

PassthroughTouchEventQueue::Config::Config() = default;
PassthroughTouchEventQueue::Config::~Config() = default;
PassthroughTouchEventQueue::Config::Config(
    const PassthroughTouchEventQueue::Config& other) = default;

// static
const base::FeatureParam<std::string>
    PassthroughTouchEventQueue::kSkipTouchEventFilterType{
        &blink::features::kSkipTouchEventFilter,
        blink::features::kSkipTouchEventFilterTypeParamName,
        blink::features::kSkipTouchEventFilterTypeParamValueDiscrete};

PassthroughTouchEventQueue::TouchEventWithLatencyInfoAndAckState::
    TouchEventWithLatencyInfoAndAckState(
        const TouchEventWithLatencyInfo& event)
    : TouchEventWithLatencyInfo(event),
      ack_state_(blink::mojom::InputEventResultState::kUnknown) {}

PassthroughTouchEventQueue::PassthroughTouchEventQueue(
    PassthroughTouchEventQueueClient* client,
    const Config& config)
    : client_(client),
      has_handlers_(true),
      maybe_has_handler_for_current_sequence_(false),
      drop_remaining_touches_in_sequence_(false),
      send_touch_events_async_(false),
      processing_acks_(false),
      skip_touch_filter_(config.skip_touch_filter),
      events_to_always_forward_(config.events_to_always_forward) {
  if (config.touch_ack_timeout_supported) {
    timeout_handler_ = std::make_unique<TouchTimeoutHandler>(
        this, config.desktop_touch_ack_timeout_delay,
        config.mobile_touch_ack_timeout_delay, config.task_runner);
  }
}

PassthroughTouchEventQueue::~PassthroughTouchEventQueue() = default;

void PassthroughTouchEventQueue::SendTouchCancelEventForTouchEvent(
    const TouchEventWithLatencyInfo& event_to_cancel) {
  TouchEventWithLatencyInfo event = event_to_cancel;
  WebTouchEventTraits::ResetTypeAndTouchStates(
      WebInputEvent::Type::kTouchCancel,
      // TODO(rbyers): Shouldn't we use a fresh timestamp?
      event.event.TimeStamp(), &event.event);
  {
    ScopedDispatchToRendererCallback dispatch_callback(
        client_->GetDispatchToRendererCallback());
    SendTouchEventImmediately(&event, false, dispatch_callback.callback);
  }
}

void PassthroughTouchEventQueue::QueueEvent(
    const TouchEventWithLatencyInfo& event,
    DispatchToRendererCallback& dispatch_callback) {
  TRACE_EVENT0("input", "PassthroughTouchEventQueue::QueueEvent");

  if (FilterBeforeForwarding(event.event) != PreFilterResult::kUnfiltered) {
    std::move(dispatch_callback)
        .Run(event.event, DispatchToRendererResult::kNotDispatched);
    client_->OnFilteringTouchEvent(event.event);

    TouchEventWithLatencyInfoAndAckState event_with_ack_state = event;
    event_with_ack_state.set_ack_info(
        blink::mojom::InputEventResultSource::kBrowser,
        blink::mojom::InputEventResultState::kNoConsumerExists);
    outstanding_touches_.insert(event_with_ack_state);
    AckCompletedEvents();
    return;
  }
  TouchEventWithLatencyInfo cloned_event(event);
  SendTouchEventImmediately(&cloned_event, true, dispatch_callback);
}

void PassthroughTouchEventQueue::PrependTouchScrollNotification(
    uint32_t primary_unique_touch_event_id) {
  TRACE_EVENT0("input",
               "PassthroughTouchEventQueue::PrependTouchScrollNotification");

  if (base::FeatureList::IsEnabled(
          blink::features::kAsyncTouchMovesImmediatelyAfterScroll)) {
    send_touch_events_async_ = true;
    SetAckStateForPendingTouchMovesFromSequence(primary_unique_touch_event_id);
  }

  TouchEventWithLatencyInfo touch(
      WebInputEvent::Type::kTouchScrollStarted, WebInputEvent::kNoModifiers,
      ui::EventTimeForNow(), LatencyInfo());
  touch.event.dispatch_type = WebInputEvent::DispatchType::kEventNonBlocking;
  touch.event.unique_touch_event_id = ui::GetNextTouchEventId();
  {
    ScopedDispatchToRendererCallback dispatch_callback(
        client_->GetDispatchToRendererCallback());
    SendTouchEventImmediately(&touch, true, dispatch_callback.callback);
  }
}

void PassthroughTouchEventQueue::SetAckStateForPendingTouchMovesFromSequence(
    uint32_t primary_unique_touch_event_id) {
  if (curr_sequence_down_event_id_ != primary_unique_touch_event_id) {
    // The touch sequence that started scroll has ended.
    return;
  }

  // Ack all outstanding touches in the current sequence to unblock the
  // browser.
  for (auto& it : outstanding_touches_) {
    if (it.event.GetType() != WebInputEvent::Type::kTouchMove) {
      break;
    }

    auto& outstanding_touch =
        const_cast<TouchEventWithLatencyInfoAndAckState&>(it);
    if (it.ack_state() == blink::mojom::InputEventResultState::kUnknown) {
      // Based on the CHECK above we are already in middle of processing acks,
      // we can just set them ignored here and the existing loop can process
      // acks for these events as well.
      outstanding_touch.set_ack_info(
          blink::mojom::InputEventResultSource::kBrowser,
          blink::mojom::InputEventResultState::kIgnored);
    }
  }
}

void PassthroughTouchEventQueue::ProcessTouchAck(
    blink::mojom::InputEventResultSource ack_source,
    blink::mojom::InputEventResultState ack_result,
    const LatencyInfo& latency_info,
    const uint32_t unique_touch_event_id,
    bool should_stop_timeout_monitor) {
  TRACE_EVENT0("input", "PassthroughTouchEventQueue::ProcessTouchAck");
  if (timeout_handler_ &&
      timeout_handler_->ConfirmTouchEvent(unique_touch_event_id, ack_result,
                                          should_stop_timeout_monitor))
    return;

  auto touch_event_iter = outstanding_touches_.find(unique_touch_event_id);
  if (touch_event_iter == outstanding_touches_.end()) {
    TRACE_EVENT_INSTANT("input", "unique_touch_event_id NotFound");
    return;
  }

  TouchEventWithLatencyInfoAndAckState& event =
      const_cast<TouchEventWithLatencyInfoAndAckState&>(*touch_event_iter);
  event.latency.AddNewLatencyFrom(latency_info);
  event.set_ack_info(ack_source, ack_result);

  AckCompletedEvents();
}

void PassthroughTouchEventQueue::OnGestureEventAck(
    const GestureEventWithLatencyInfo& event,
    blink::mojom::InputEventResultState ack_result) {
  // When the scroll finishes allow TouchEvents to be blocking again.
  if (event.event.GetType() == blink::WebInputEvent::Type::kGestureScrollEnd) {
    send_touch_events_async_ = false;
  } else if (event.event.GetType() ==
                 blink::WebInputEvent::Type::kGestureScrollUpdate &&
             ack_result == blink::mojom::InputEventResultState::kConsumed) {
    send_touch_events_async_ = true;
  }
}

void PassthroughTouchEventQueue::OnHasTouchEventHandlers(bool has_handlers) {
  has_handlers_ = has_handlers;
}

bool PassthroughTouchEventQueue::IsPendingAckTouchStart() const {
  if (outstanding_touches_.empty())
    return false;

  for (auto& iter : outstanding_touches_) {
    if (iter.event.GetType() == WebInputEvent::Type::kTouchStart)
      return true;
  }
  return false;
}

void PassthroughTouchEventQueue::SetAckTimeoutEnabled(bool enabled) {
  if (timeout_handler_)
    timeout_handler_->SetEnabled(enabled);
}

void PassthroughTouchEventQueue::SetIsMobileOptimizedSite(
    bool mobile_optimized_site) {
  if (timeout_handler_)
    timeout_handler_->SetUseMobileTimeout(mobile_optimized_site);
}

bool PassthroughTouchEventQueue::IsAckTimeoutEnabled() const {
  return timeout_handler_ && timeout_handler_->IsEnabled();
}

bool PassthroughTouchEventQueue::Empty() const {
  return outstanding_touches_.empty();
}

void PassthroughTouchEventQueue::FlushQueue() {
  // Don't allow acks to be processed in AckCompletedEvents as that can
  // interfere with gesture event dispatch ordering.
  base::AutoReset<bool> process_acks(&processing_acks_, true);
  drop_remaining_touches_in_sequence_ = true;
  client_->FlushDeferredGestureQueue();
  while (!outstanding_touches_.empty()) {
    auto iter = outstanding_touches_.begin();
    TouchEventWithLatencyInfoAndAckState event = *iter;
    outstanding_touches_.erase(iter);
    if (event.ack_state() == blink::mojom::InputEventResultState::kUnknown)
      event.set_ack_info(
          blink::mojom::InputEventResultSource::kBrowser,
          blink::mojom::InputEventResultState::kNoConsumerExists);
    AckTouchEventToClient(event, event.ack_source(), event.ack_state());
  }
}

void PassthroughTouchEventQueue::OnTouchActionFromMain() {
  if (base::FeatureList::IsEnabled(
          blink::features::kAsyncTouchMovesImmediatelyAfterScroll)) {
    // It's possible a deferred scroll might have actually started upon
    // receiving touch action from main. And as a result ack of some touch moves
    // would have been set locally in Browser itself in
    // `SetAckStateForPendingTouchMovesFromSequence`.
    AckCompletedEvents();
  }
}

void PassthroughTouchEventQueue::StopTimeoutMonitor() {
  if (timeout_handler_)
    timeout_handler_->StopTimeoutMonitor();
}

void PassthroughTouchEventQueue::AckCompletedEvents() {
  // Don't allow re-entrancy into this method otherwise
  // the ordering of acks won't be preserved.
  if (processing_acks_) {
    TRACE_EVENT_INSTANT("input", "ProcessingAcksAlready");
    return;
  }
  base::AutoReset<bool> process_acks(&processing_acks_, true);
  while (!outstanding_touches_.empty()) {
    auto iter = outstanding_touches_.begin();
    if (iter->ack_state() == blink::mojom::InputEventResultState::kUnknown) {
      TRACE_EVENT_INSTANT("input", "Unknown InputEventResultState");
      break;
    }
    TouchEventWithLatencyInfoAndAckState event = *iter;
    outstanding_touches_.erase(iter);
    AckTouchEventToClient(event, event.ack_source(), event.ack_state());
  }
}

void PassthroughTouchEventQueue::AckTouchEventToClient(
    const TouchEventWithLatencyInfo& acked_event,
    blink::mojom::InputEventResultSource ack_source,
    blink::mojom::InputEventResultState ack_result) {
  UpdateTouchConsumerStates(acked_event.event, ack_result);

  // Skip ack for TouchScrollStarted since it was synthesized within the queue.
  if (acked_event.event.GetType() != WebInputEvent::Type::kTouchScrollStarted) {
    client_->OnTouchEventAck(acked_event, ack_source, ack_result);
  }
}

void PassthroughTouchEventQueue::SendTouchEventImmediately(
    TouchEventWithLatencyInfo* touch,
    bool wait_for_ack,
    DispatchToRendererCallback& dispatch_callback) {
  // Note: Touchstart events are marked cancelable to allow transitions between
  // platform scrolling and JS pinching. Touchend events, however, remain
  // uncancelable, mitigating the risk of jank when transitioning to a fling.
  if (send_touch_events_async_ &&
      touch->event.GetType() != WebInputEvent::Type::kTouchStart)
    touch->event.dispatch_type = WebInputEvent::DispatchType::kEventNonBlocking;

  if (touch->event.GetType() == WebInputEvent::Type::kTouchStart) {
    touch->event.touch_start_or_first_touch_move = true;
    any_touchmove_moved_beyond_slop_region_ = false;
  }

  // For touchmove events, compare touch points position from current event
  // to last sent event and update touch points state.
  if (touch->event.GetType() == WebInputEvent::Type::kTouchMove) {
    CHECK(last_sent_touchevent_);
    if (last_sent_touchevent_->GetType() == WebInputEvent::Type::kTouchStart ||
        (last_sent_touchevent_->GetType() == WebInputEvent::Type::kTouchMove &&
         !any_touchmove_moved_beyond_slop_region_)) {
      touch->event.touch_start_or_first_touch_move = true;
      any_touchmove_moved_beyond_slop_region_ |=
          touch->event.moved_beyond_slop_region;
    }
    for (unsigned int i = 0; i < last_sent_touchevent_->touches_length; ++i) {
      const WebTouchPoint& last_touch_point = last_sent_touchevent_->touches[i];
      // Touches with same id may not have same index in Touches array.
      for (unsigned int j = 0; j < touch->event.touches_length; ++j) {
        const WebTouchPoint& current_touchmove_point = touch->event.touches[j];
        if (current_touchmove_point.id != last_touch_point.id)
          continue;

        if (!HasPointChanged(last_touch_point, current_touchmove_point))
          touch->event.touches[j].state =
              WebTouchPoint::State::kStateStationary;

        break;
      }
    }
  }

  if (touch->event.GetType() != WebInputEvent::Type::kTouchScrollStarted) {
    if (last_sent_touchevent_)
      *last_sent_touchevent_ = touch->event;
    else
      last_sent_touchevent_ = std::make_unique<WebTouchEvent>(touch->event);
  }

  if (touch->event.IsTouchSequenceStart()) {
    curr_sequence_down_event_id_ = touch->event.unique_touch_event_id;
  } else if (touch->event.IsTouchSequenceEnd()) {
    curr_sequence_down_event_id_.reset();
  }

  if (timeout_handler_)
    timeout_handler_->StartIfNecessary(*touch);
  touch->event.GetModifiableEventLatencyMetadata().dispatched_to_renderer =
      base::TimeTicks::Now();
  if (wait_for_ack)
    outstanding_touches_.insert(*touch);
  client_->SendTouchEventImmediately(*touch, dispatch_callback);
}

PassthroughTouchEventQueue::PreFilterResult
PassthroughTouchEventQueue::FilterBeforeForwarding(const WebTouchEvent& event) {
  PreFilterResult result = FilterBeforeForwardingImpl(event);
  if (result == PreFilterResult::kFilteredTimeout ||
      result == PreFilterResult::kFilteredNoNonstationaryPointers)
    return result;

  // Override non-timeout filter results based on the Finch trial that bypasses
  // the filter. We do this here so that the event still has the opportunity to
  // update any internal state that's necessary to handle future events
  // (i.e. future touch moves might be dropped, even if this touch start isn't
  // due to a filter override).
  if (!ShouldFilterForEvent(event))
    return PreFilterResult::kUnfiltered;

  return result;
}

bool PassthroughTouchEventQueue::ShouldFilterForEvent(
    const blink::WebTouchEvent& event) {
  // Always run all filtering if the SkipTouchEventFilter is disabled.
  if (!skip_touch_filter_)
    return true;
  // If the experiment is enabled and all events are forwarded, always skip
  // filtering.
  if (events_to_always_forward_ ==
      blink::features::kSkipTouchEventFilterTypeParamValueAll)
    return false;
  // If the experiment is enabled and only discrete events are forwarded,
  // always run filtering for touchmove events only.
  return event.GetType() == WebInputEvent::Type::kTouchMove;
}

PassthroughTouchEventQueue::PreFilterResult
PassthroughTouchEventQueue::FilterBeforeForwardingImpl(
    const WebTouchEvent& event) {
  // Unconditionally apply the timeout filter to avoid exacerbating
  // any responsiveness problems on the page.
  if (timeout_handler_ && timeout_handler_->FilterEvent(event))
    return PreFilterResult::kFilteredTimeout;

  if (event.GetType() == WebInputEvent::Type::kTouchScrollStarted)
    return PreFilterResult::kUnfiltered;

  if (event.IsTouchSequenceStart()) {
    // We don't know if we have a handler until we get the ACK back so
    // assume it is true.
    maybe_has_handler_for_current_sequence_ = true;
    send_touch_events_async_ = false;
    last_sent_touchevent_.reset();

    drop_remaining_touches_in_sequence_ = false;
    if (!has_handlers_) {
      drop_remaining_touches_in_sequence_ = true;
      // If the SkipTouchEventFilter experiment is running, drop through to
      // the loop that filters events with no nonstationary pointers below.
      if (ShouldFilterForEvent(event))
        return PreFilterResult::kFilteredNoPageHandlers;
    }
  }

  if (drop_remaining_touches_in_sequence_ &&
      event.GetType() != WebInputEvent::Type::kTouchCancel &&
      // If the SkipTouchEventFilter experiment is running, drop through to
      // the loop that filters events with no nonstationary pointers below.
      ShouldFilterForEvent(event))
    return PreFilterResult::kFilteredNoPageHandlers;

  if (event.GetType() == WebInputEvent::Type::kTouchStart) {
    if (has_handlers_ || maybe_has_handler_for_current_sequence_)
      return PreFilterResult::kUnfiltered;
    // If the SkipTouchEventFilter experiment is running, drop through to
    // the loop that filters events with no nonstationary pointers below.
    else if (ShouldFilterForEvent(event))
      return PreFilterResult::kFilteredNoPageHandlers;
  }

  // If none of the touch points active in the current sequence have handlers,
  // don't forward the touch event.
  if (!maybe_has_handler_for_current_sequence_ && ShouldFilterForEvent(event))
    return PreFilterResult::kFilteredNoHandlerForSequence;

  // Only forward a touch if it has a non-stationary pointer that is active
  // in the current touch sequence.
  for (size_t i = 0; i < event.touches_length; ++i) {
    const WebTouchPoint& point = event.touches[i];
    if (point.state == WebTouchPoint::State::kStateStationary)
      continue;

    // |last_sent_touchevent_| will be non-null as long as there is an
    // active touch sequence being forwarded to the renderer.
    if (!last_sent_touchevent_)
      continue;

    for (size_t j = 0; j < last_sent_touchevent_->touches_length; ++j) {
      if (point.id != last_sent_touchevent_->touches[j].id)
        continue;

      if (event.GetType() != WebInputEvent::Type::kTouchMove)
        return PreFilterResult::kUnfiltered;

      // All pointers in TouchMove events may have state as StateMoved,
      // even though none of the pointers have not changed in real.
      // Forward these events when at least one pointer has changed.
      if (HasPointChanged(last_sent_touchevent_->touches[j], point))
        return PreFilterResult::kUnfiltered;

      // This is a TouchMove event for which we have yet to find a
      // non-stationary pointer. Continue checking the next pointers
      // in the |event|.
      break;
    }
  }

  return PreFilterResult::kFilteredNoNonstationaryPointers;
}

void PassthroughTouchEventQueue::UpdateTouchConsumerStates(
    const WebTouchEvent& event,
    blink::mojom::InputEventResultState ack_result) {
  if (event.GetType() == WebInputEvent::Type::kTouchStart) {
    if (ack_result == blink::mojom::InputEventResultState::kConsumed)
      send_touch_events_async_ = false;

    // Once we have the ack back for the sequence we know if there
    // is a handler or not. Other touch-starts sent can upgrade
    // whether we have a handler or not as well.
    if (event.IsTouchSequenceStart()) {
      maybe_has_handler_for_current_sequence_ =
          ack_result != blink::mojom::InputEventResultState::kNoConsumerExists;
    } else {
      maybe_has_handler_for_current_sequence_ |=
          ack_result != blink::mojom::InputEventResultState::kNoConsumerExists;
    }
  } else if (event.IsTouchSequenceEnd()) {
    maybe_has_handler_for_current_sequence_ = false;
  }
}

size_t PassthroughTouchEventQueue::SizeForTesting() const {
  return outstanding_touches_.size();
}

bool PassthroughTouchEventQueue::IsTimeoutRunningForTesting() const {
  return timeout_handler_ && timeout_handler_->IsTimeoutTimerRunning();
}

}  // namespace input
