chromium/third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.cc

// 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 "third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.h"

#include <utility>

#include "base/check_op.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/metrics/histogram_macros.h"
#include "base/notreached.h"
#include "base/task/single_thread_task_runner.h"
#include "base/time/time.h"
#include "base/types/optional_ref.h"
#include "base/types/pass_key.h"
#include "build/build_config.h"
#include "cc/base/features.h"
#include "cc/input/browser_controls_offset_tags_info.h"
#include "cc/metrics/event_metrics.h"
#include "cc/trees/layer_tree_host.h"
#include "cc/trees/paint_holding_reason.h"
#include "components/viz/common/features.h"
#include "services/tracing/public/cpp/perfetto/flow_event_utils.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/input/web_coalesced_input_event.h"
#include "third_party/blink/public/common/input/web_input_event_attribution.h"
#include "third_party/blink/public/common/input/web_keyboard_event.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/scheduler/public/agent_group_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/public/compositor_thread_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/public/widget_scheduler.h"
#include "third_party/blink/renderer/platform/widget/frame_widget.h"
#include "third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller.h"
#include "third_party/blink/renderer/platform/widget/input/main_thread_event_queue.h"
#include "third_party/blink/renderer/platform/widget/input/widget_input_handler_impl.h"
#include "third_party/blink/renderer/platform/widget/widget_base.h"
#include "third_party/blink/renderer/platform/widget/widget_base_client.h"

#if BUILDFLAG(IS_ANDROID)
#include "third_party/blink/renderer/platform/widget/compositing/android_webview/synchronous_compositor_registry.h"
#include "third_party/blink/renderer/platform/widget/input/synchronous_compositor_proxy.h"
#endif

namespace blink {

ChromeLatencyInfo;
TrackEvent;

namespace {
// We will count dropped pointerdown by posting a task in the main thread.
// To avoid blocking the main thread, we need a timer to send the data
// intermittently. The time delay of the timer is 10X of the threshold of
// long tasks which block the main thread 50 ms or longer.
const base::TimeDelta kEventCountsTimerDelay =;

// The 99th percentile of the delay between navigation start and first paint is
// around 10sec on most platforms.  We are setting the max acceptable limit to
// 1.5x to avoid false positives on slow devices.
const base::TimeDelta kFirstPaintMaxAcceptableDelay =;

mojom::blink::DidOverscrollParamsPtr ToDidOverscrollParams(
    const InputHandlerProxy::DidOverscrollParams* overscroll_params) {}

void CallCallback(
    mojom::blink::WidgetInputHandler::DispatchEventCallback callback,
    mojom::blink::InputEventResultState result_state,
    const ui::LatencyInfo& latency_info,
    mojom::blink::DidOverscrollParamsPtr overscroll_params,
    std::optional<cc::TouchAction> touch_action) {}

mojom::blink::InputEventResultState InputEventDispositionToAck(
    InputHandlerProxy::EventDisposition disposition) {}

}  // namespace

#if BUILDFLAG(IS_ANDROID)
class SynchronousCompositorProxyRegistry
    : public SynchronousCompositorRegistry {
 public:
  explicit SynchronousCompositorProxyRegistry(
      scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner,
      base::PlatformThreadId io_thread_id,
      base::PlatformThreadId main_thread_id)
      : compositor_thread_default_task_runner_(
            std::move(compositor_task_runner)),
        io_thread_id_(io_thread_id),
        main_thread_id_(main_thread_id) {}

  ~SynchronousCompositorProxyRegistry() override {
    // Ensure the proxy has already been release on the compositor thread
    // before destroying this object.
    DCHECK(!proxy_);
  }

  void CreateProxy(InputHandlerProxy* handler) {
    DCHECK(compositor_thread_default_task_runner_->BelongsToCurrentThread());
    proxy_ = std::make_unique<SynchronousCompositorProxy>(handler);

    proxy_->Init();

    if (base::FeatureList::IsEnabled(::features::kWebViewEnableADPF)) {
      Vector<base::PlatformThreadId> renderer_thread_ids;
      renderer_thread_ids.push_back(base::PlatformThread::CurrentId());
      if (io_thread_id_ != base::kInvalidThreadId) {
        renderer_thread_ids.push_back(io_thread_id_);
      }
      if (main_thread_id_ != base::kInvalidThreadId &&
          base::FeatureList::IsEnabled(
              ::features::kWebViewEnableADPFRendererMain)) {
        renderer_thread_ids.push_back(main_thread_id_);
      }
      proxy_->SetThreadIds(renderer_thread_ids);
    }

    if (sink_)
      proxy_->SetLayerTreeFrameSink(sink_);
  }

  SynchronousCompositorProxy* proxy() { return proxy_.get(); }

  void RegisterLayerTreeFrameSink(
      SynchronousLayerTreeFrameSink* layer_tree_frame_sink) override {
    DCHECK(compositor_thread_default_task_runner_->BelongsToCurrentThread());
    DCHECK_EQ(nullptr, sink_);
    sink_ = layer_tree_frame_sink;
    if (proxy_)
      proxy_->SetLayerTreeFrameSink(layer_tree_frame_sink);
  }

  void UnregisterLayerTreeFrameSink(
      SynchronousLayerTreeFrameSink* layer_tree_frame_sink) override {
    DCHECK(compositor_thread_default_task_runner_->BelongsToCurrentThread());
    DCHECK_EQ(layer_tree_frame_sink, sink_);
    sink_ = nullptr;
  }

  void DestroyProxy() {
    DCHECK(compositor_thread_default_task_runner_->BelongsToCurrentThread());
    proxy_.reset();
  }

 private:
  scoped_refptr<base::SingleThreadTaskRunner>
      compositor_thread_default_task_runner_;
  std::unique_ptr<SynchronousCompositorProxy> proxy_;
  raw_ptr<SynchronousLayerTreeFrameSink> sink_ = nullptr;
  base::PlatformThreadId io_thread_id_;
  base::PlatformThreadId main_thread_id_;
};

#endif

scoped_refptr<WidgetInputHandlerManager> WidgetInputHandlerManager::Create(
    base::WeakPtr<WidgetBase> widget,
    base::WeakPtr<mojom::blink::FrameWidgetInputHandler>
        frame_widget_input_handler,
    bool never_composited,
    CompositorThreadScheduler* compositor_thread_scheduler,
    scoped_refptr<scheduler::WidgetScheduler> widget_scheduler,
    bool uses_input_handler,
    bool allow_scroll_resampling,
    base::PlatformThreadId io_thread_id,
    base::PlatformThreadId main_thread_id) {}

WidgetInputHandlerManager::WidgetInputHandlerManager(
    base::PassKey<WidgetInputHandlerManager>,
    base::WeakPtr<WidgetBase> widget,
    base::WeakPtr<mojom::blink::FrameWidgetInputHandler>
        frame_widget_input_handler,
    bool never_composited,
    CompositorThreadScheduler* compositor_thread_scheduler,
    scoped_refptr<scheduler::WidgetScheduler> widget_scheduler,
    bool allow_scroll_resampling,
    base::PlatformThreadId io_thread_id,
    base::PlatformThreadId main_thread_id)
    :{}

void WidgetInputHandlerManager::DidFirstVisuallyNonEmptyPaint(
    const base::TimeTicks& first_paint_time) {}

void WidgetInputHandlerManager::InitInputHandler() {}

WidgetInputHandlerManager::~WidgetInputHandlerManager() = default;

void WidgetInputHandlerManager::AddInterface(
    mojo::PendingReceiver<mojom::blink::WidgetInputHandler> receiver,
    mojo::PendingRemote<mojom::blink::WidgetInputHandlerHost> host) {}

bool WidgetInputHandlerManager::HandleInputEvent(
    const WebCoalescedInputEvent& event,
    std::unique_ptr<cc::EventMetrics> metrics,
    HandledEventCallback handled_callback) {}

void WidgetInputHandlerManager::InputEventsDispatched(bool raf_aligned) {}

void WidgetInputHandlerManager::SetNeedsMainFrame() {}

bool WidgetInputHandlerManager::RequestedMainFramePending() {}

void WidgetInputHandlerManager::WillShutdown() {}

void WidgetInputHandlerManager::FindScrollTargetOnMainThread(
    const gfx::PointF& point,
    ElementAtPointCallback callback) {}

void WidgetInputHandlerManager::DidStartScrollingViewport() {}

void WidgetInputHandlerManager::SetAllowedTouchAction(
    cc::TouchAction touch_action) {}

void WidgetInputHandlerManager::ProcessTouchAction(
    cc::TouchAction touch_action) {}

mojom::blink::WidgetInputHandlerHost*
WidgetInputHandlerManager::GetWidgetInputHandlerHost() {}

#if BUILDFLAG(IS_ANDROID)
void WidgetInputHandlerManager::AttachSynchronousCompositor(
    mojo::PendingRemote<mojom::blink::SynchronousCompositorControlHost>
        control_host,
    mojo::PendingAssociatedRemote<mojom::blink::SynchronousCompositorHost> host,
    mojo::PendingAssociatedReceiver<mojom::blink::SynchronousCompositor>
        compositor_request) {
  DCHECK(synchronous_compositor_registry_);
  if (synchronous_compositor_registry_->proxy()) {
    synchronous_compositor_registry_->proxy()->BindChannel(
        std::move(control_host), std::move(host),
        std::move(compositor_request));
  }
}
#endif

void WidgetInputHandlerManager::ObserveGestureEventOnMainThread(
    const WebGestureEvent& gesture_event,
    const cc::InputHandlerScrollResult& scroll_result) {}

void WidgetInputHandlerManager::LogInputTimingUMA() {}

void WidgetInputHandlerManager::RecordEventMetricsForPaintTiming(
    std::optional<base::TimeTicks> first_paint_time) {}

void WidgetInputHandlerManager::StartFirstPaintMaxDelayTimer() {}

void WidgetInputHandlerManager::DispatchScrollGestureToCompositor(
    std::unique_ptr<WebGestureEvent> event) {}

void WidgetInputHandlerManager::
    HandleInputEventWithLatencyOnInputHandlingThread(
        std::unique_ptr<WebCoalescedInputEvent> event) {}

void WidgetInputHandlerManager::DispatchEventOnInputThreadForTesting(
    std::unique_ptr<blink::WebCoalescedInputEvent> event,
    mojom::blink::WidgetInputHandler::DispatchEventCallback callback) {}

void WidgetInputHandlerManager::DispatchEvent(
    std::unique_ptr<WebCoalescedInputEvent> event,
    mojom::blink::WidgetInputHandler::DispatchEventCallback callback) {}

void WidgetInputHandlerManager::InvokeInputProcessedCallback() {}

static void WaitForInputProcessedFromMain(base::WeakPtr<WidgetBase> widget) {}

void WidgetInputHandlerManager::WaitForInputProcessed(
    base::OnceClosure callback) {}

void WidgetInputHandlerManager::InitializeInputEventSuppressionStates() {}

void WidgetInputHandlerManager::OnDeferMainFrameUpdatesChanged(bool status) {}

void WidgetInputHandlerManager::OnDeferCommitsChanged(
    bool status,
    cc::PaintHoldingReason reason) {}

void WidgetInputHandlerManager::InitOnInputHandlingThread(
    const base::WeakPtr<cc::CompositorDelegateForInput>& compositor_delegate,
    bool sync_compositing) {}

void WidgetInputHandlerManager::BindChannel(
    mojo::PendingReceiver<mojom::blink::WidgetInputHandler> receiver) {}

void WidgetInputHandlerManager::DispatchDirectlyToWidget(
    std::unique_ptr<WebCoalescedInputEvent> event,
    std::unique_ptr<cc::EventMetrics> metrics,
    mojom::blink::WidgetInputHandler::DispatchEventCallback callback) {}

void WidgetInputHandlerManager::FindScrollTargetReply(
    std::unique_ptr<WebCoalescedInputEvent> event,
    std::unique_ptr<cc::EventMetrics> metrics,
    mojom::blink::WidgetInputHandler::DispatchEventCallback browser_callback,
    cc::ElementId hit_test_result) {}

void WidgetInputHandlerManager::SendDroppedPointerDownCounts() {}

void WidgetInputHandlerManager::DidHandleInputEventSentToCompositor(
    mojom::blink::WidgetInputHandler::DispatchEventCallback callback,
    InputHandlerProxy::EventDisposition event_disposition,
    std::unique_ptr<WebCoalescedInputEvent> event,
    std::unique_ptr<InputHandlerProxy::DidOverscrollParams> overscroll_params,
    const WebInputEventAttribution& attribution,
    std::unique_ptr<cc::EventMetrics> metrics) {}

void WidgetInputHandlerManager::DidHandleInputEventSentToMainFromWidgetBase(
    mojom::blink::WidgetInputHandler::DispatchEventCallback callback,
    mojom::blink::InputEventResultState ack_state,
    const ui::LatencyInfo& latency_info,
    std::unique_ptr<blink::InputHandlerProxy::DidOverscrollParams>
        overscroll_params,
    std::optional<cc::TouchAction> touch_action) {}

void WidgetInputHandlerManager::DidHandleInputEventSentToMain(
    mojom::blink::WidgetInputHandler::DispatchEventCallback callback,
    std::optional<cc::TouchAction> touch_action_from_compositor,
    mojom::blink::InputEventResultState ack_state,
    const ui::LatencyInfo& latency_info,
    mojom::blink::DidOverscrollParamsPtr overscroll_params,
    std::optional<cc::TouchAction> touch_action_from_main) {}

void WidgetInputHandlerManager::ObserveGestureEventOnInputHandlingThread(
    const WebGestureEvent& gesture_event,
    const cc::InputHandlerScrollResult& scroll_result) {}

const scoped_refptr<base::SingleThreadTaskRunner>&
WidgetInputHandlerManager::InputThreadTaskRunner(TaskRunnerType type) const {}

#if BUILDFLAG(IS_ANDROID)
SynchronousCompositorRegistry*
WidgetInputHandlerManager::GetSynchronousCompositorRegistry() {
  DCHECK(synchronous_compositor_registry_);
  return synchronous_compositor_registry_.get();
}
#endif

void WidgetInputHandlerManager::ClearClient() {}

void WidgetInputHandlerManager::UpdateBrowserControlsState(
    cc::BrowserControlsState constraints,
    cc::BrowserControlsState current,
    bool animate,
    base::optional_ref<const cc::BrowserControlsOffsetTagsInfo>
        offset_tags_info) {}

void WidgetInputHandlerManager::FlushCompositorQueueForTesting() {}

void WidgetInputHandlerManager::FlushMainThreadQueueForTesting(
    base::OnceClosure done) {}

void WidgetInputHandlerManager::FlushEventQueuesForTesting(
    base::OnceClosure done_callback) {}

}  // namespace blink