chromium/content/browser/renderer_host/input/touch_action_browsertest.cc

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

#include <string_view>
#include <tuple>
#include <utility>

#include "base/auto_reset.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/json/json_reader.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/bind.h"
#include "base/test/gmock_expected_support.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/input/actions_parser.h"
#include "content/common/input/synthetic_gesture.h"
#include "content/common/input/synthetic_gesture_controller.h"
#include "content/common/input/synthetic_gesture_params.h"
#include "content/common/input/synthetic_gesture_target.h"
#include "content/common/input/synthetic_pointer_action.h"
#include "content/common/input/synthetic_pointer_action_list_params.h"
#include "content/common/input/synthetic_smooth_scroll_gesture.h"
#include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/hit_test_region_observer.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "third_party/blink/public/common/input/web_input_event.h"
#include "ui/base/ui_base_features.h"
#include "ui/events/blink/blink_features.h"
#include "ui/latency/latency_info.h"

WebInputEvent;

namespace {

constexpr char kTouchActionDataURL[] =;

constexpr char kTouchActionURLWithOverlapArea[] =;

void GiveItSomeTime(int t) {}

constexpr base::TimeDelta kNoJankTime =;
constexpr base::TimeDelta kShortJankTime =;
// 1200ms is larger than both desktop / mobile_touch_ack_timeout_delay in the
// PassthroughTouchEventQueue, which ensures timeout to be triggered.
constexpr base::TimeDelta kLongJankTime =;
}  // namespace

namespace content {

class TouchActionBrowserTest : public ContentBrowserTest {};

// TODO(crbug.com/40236573): Fix Mac failures.
#if !defined(NDEBUG) || defined(ADDRESS_SANITIZER) ||       \
    defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER) || \
    defined(THREAD_SANITIZER) || BUILDFLAG(IS_MAC)
#define MAYBE_DefaultAuto
#else
#define MAYBE_DefaultAuto
#endif
//
// Verify the test infrastructure works - we can touch-scroll the page and get a
// touchcancel as expected.
IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest, MAYBE_DefaultAuto) {}

// Verify that touching a touch-action: none region disables scrolling and
// enables all touch events to be sent.
#if !defined(NDEBUG) || defined(ADDRESS_SANITIZER) ||       \
    defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER) || \
    defined(THREAD_SANITIZER)
#define MAYBE_TouchActionNone
#else
#define MAYBE_TouchActionNone
#endif
IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest, MAYBE_TouchActionNone) {}

// TODO(crbug.com/40236573): Fix Mac failures.
#if !defined(NDEBUG) || defined(ADDRESS_SANITIZER) ||       \
    defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER) || \
    defined(THREAD_SANITIZER) || BUILDFLAG(IS_MAC)
#define MAYBE_PanYMainThreadJanky
#else
#define MAYBE_PanYMainThreadJanky
#endif
IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest, MAYBE_PanYMainThreadJanky) {}

// TODO(crbug.com/40236573): Fix Mac failures.
#if !defined(NDEBUG) || defined(ADDRESS_SANITIZER) ||       \
    defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER) || \
    defined(THREAD_SANITIZER) || BUILDFLAG(IS_MAC)
#define MAYBE_PanXMainThreadJanky
#else
#define MAYBE_PanXMainThreadJanky
#endif
IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest, MAYBE_PanXMainThreadJanky) {}

#if BUILDFLAG(IS_ANDROID)
#define MAYBE_PanXAtYAreaWithTimeout
#else
#define MAYBE_PanXAtYAreaWithTimeout
#endif
// When touch ack timeout is triggered, the panx gesture will be allowed even
// though we touch the pany area.
IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest, MAYBE_PanXAtYAreaWithTimeout) {}

#if BUILDFLAG(IS_ANDROID)
#define MAYBE_TwoFingerPanXAtYAreaWithTimeout
#else
#define MAYBE_TwoFingerPanXAtYAreaWithTimeout
#endif
// When touch ack timeout is triggered, the panx gesture will be allowed even
// though we touch the pany area.
IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest,
                       MAYBE_TwoFingerPanXAtYAreaWithTimeout) {}

// TODO(crbug.com/40236573): Fix Mac failures.
#if !defined(NDEBUG) || defined(ADDRESS_SANITIZER) ||       \
    defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER) || \
    defined(THREAD_SANITIZER) || BUILDFLAG(IS_MAC)
#define MAYBE_PanXYMainThreadJanky
#else
#define MAYBE_PanXYMainThreadJanky
#endif
IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest, MAYBE_PanXYMainThreadJanky) {}

// TODO(crbug.com/40236573): Fix Mac failures.
#if !defined(NDEBUG) || defined(ADDRESS_SANITIZER) ||       \
    defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER) || \
    defined(THREAD_SANITIZER) || BUILDFLAG(IS_MAC)
#define MAYBE_PanXYAtXAreaMainThreadJanky
#else
#define MAYBE_PanXYAtXAreaMainThreadJanky
#endif
IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest,
                       MAYBE_PanXYAtXAreaMainThreadJanky) {}

// TODO(crbug.com/40236573): Fix Mac failures.
#if !defined(NDEBUG) || defined(ADDRESS_SANITIZER) ||       \
    defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER) || \
    defined(THREAD_SANITIZER) || BUILDFLAG(IS_MAC)
#define MAYBE_PanXYAtYAreaMainThreadJanky
#else
#define MAYBE_PanXYAtYAreaMainThreadJanky
#endif
IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest,
                       MAYBE_PanXYAtYAreaMainThreadJanky) {}

// TODO(crbug.com/40236573): Fix Mac failures.
#if !defined(NDEBUG) || defined(ADDRESS_SANITIZER) ||       \
    defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER) || \
    defined(THREAD_SANITIZER) || BUILDFLAG(IS_MAC)
#define MAYBE_PanXYAtAutoYOverlapAreaMainThreadJanky
#else
#define MAYBE_PanXYAtAutoYOverlapAreaMainThreadJanky
#endif
IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest,
                       MAYBE_PanXYAtAutoYOverlapAreaMainThreadJanky) {}

// TODO(crbug.com/40236573): Fix Mac failures.
#if !defined(NDEBUG) || defined(ADDRESS_SANITIZER) ||       \
    defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER) || \
    defined(THREAD_SANITIZER) || BUILDFLAG(IS_MAC)
#define MAYBE_PanXYAtAutoXOverlapAreaMainThreadJanky
#else
#define MAYBE_PanXYAtAutoXOverlapAreaMainThreadJanky
#endif
IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest,
                       MAYBE_PanXYAtAutoXOverlapAreaMainThreadJanky) {}

// TODO(crbug.com/41422733): Make this test work on Android.
#if BUILDFLAG(IS_ANDROID)
#define MAYBE_TwoFingerPanYDisallowed
#else
#define MAYBE_TwoFingerPanYDisallowed
#endif
// Test that two finger panning is treated as pinch zoom and is disallowed when
// touching the pan-y area.
IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest, MAYBE_TwoFingerPanYDisallowed) {}

namespace {

const std::string kDoubleTapZoomDataURL =;

}  // namespace

// Test that |touch-action: none| correctly blocks a double-tap and drag zoom
// gesture.
IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest, BlockDoubleTapDragZoom) {}

namespace {

constexpr char kContentEditableDataURL[] =;

constexpr char kContentEditableHorizontalScrollableDataURL[] =;

constexpr char kContentEditableNonPassiveHandlerDataURL[] =;

constexpr char kInputTagCursorControl[] =;

}  // namespace

class TouchActionBrowserTestEnableCursorControl
    : public TouchActionBrowserTest {};

// Perform a horizontal swipe over an editable element from right to left.
// Ensure the swipe is interpreted as a cursor control movement, rather than a
// scroll, and changes the selection.
IN_PROC_BROWSER_TEST_F(TouchActionBrowserTestEnableCursorControl,
                       BasicCursorControl) {}

// Perform a horizontal swipe over an editable element from right to left (the
// element shift to left), the element is inside of a horizontal scroller.
// Ensure the swipe is interpreted as a normal scroll, selection should not be
// changed and scroll should happen.
IN_PROC_BROWSER_TEST_F(TouchActionBrowserTestEnableCursorControl,
                       NoCursorControlForHorizontalScrollable) {}

// Perform a horizontal swipe over an editable element from right to left
// Ensure the swipe is not triggering cursor control.
IN_PROC_BROWSER_TEST_F(TouchActionBrowserTestEnableCursorControl,
                       NoCursorControlForNonPassiveLisenter) {}

// Perform a horizontal swipe over an input element from right to left.
// Ensure the swipe is interpreted as a cursor control movement, rather than a
// scroll, and changes the selection.
IN_PROC_BROWSER_TEST_F(TouchActionBrowserTestEnableCursorControl,
                       CursorControlOnInput) {}

// Perform a horizontal swipe over an horizontal scrollable input element from
// right to left. Ensure the swipe is doing scrolling other than cursor control.
IN_PROC_BROWSER_TEST_F(TouchActionBrowserTestEnableCursorControl,
                       NoCursorControlOnHorizontalScrollableInput) {}

}  // namespace content