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

#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/bind.h"
#include "base/test/run_until.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_timeouts.h"
#include "build/build_config.h"
#include "content/browser/renderer_host/cross_process_frame_connector.h"
#include "content/browser/renderer_host/frame_tree.h"
#include "content/browser/renderer_host/render_frame_proxy_host.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/site_per_process_browsertest.h"
#include "content/common/input/synthetic_smooth_scroll_gesture.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_utils.h"
#include "content/public/test/hit_test_region_observer.h"
#include "content/public/test/synchronize_visual_properties_interceptor.h"
#include "content/public/test/test_frame_navigation_observer.h"
#include "content/test/render_document_feature.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/input/web_touch_event.h"
#include "ui/events/gesture_detection/gesture_configuration.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/native_theme/features/native_theme_features.h"

namespace content {

class ScrollingIntegrationTest : public SitePerProcessBrowserTest {
 public:
  ScrollingIntegrationTest() = default;
  ~ScrollingIntegrationTest() override = default;

  void DoScroll(const gfx::Point& point,
                const gfx::Vector2d& distance,
                content::mojom::GestureSourceType source) {
    SyntheticSmoothScrollGestureParams params;
    params.gesture_source_type = source;
    params.anchor = gfx::PointF(point);
    params.distances.push_back(-distance);
    params.granularity = ui::ScrollGranularity::kScrollByPrecisePixel;

    auto gesture = std::make_unique<SyntheticSmoothScrollGesture>(params);

    // Runs until we get the SyntheticGestureCompleted callback
    base::RunLoop run_loop;
    GetRenderWidgetHostImpl()->QueueSyntheticGesture(
        std::move(gesture),
        base::BindLambdaForTesting([&](SyntheticGesture::Result result) {
          EXPECT_EQ(SyntheticGesture::GESTURE_FINISHED, result);
          run_loop.Quit();
        }));
    run_loop.Run();
  }

  double GetScrollTop() {
    FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
                              ->GetPrimaryFrameTree()
                              .root();
    return EvalJs(root, "window.scrollY").ExtractDouble();
  }

  void WaitForVerticalScroll() {
    RenderFrameSubmissionObserver frame_observer(shell()->web_contents());
    gfx::PointF default_scroll_offset;
    while (frame_observer.LastRenderFrameMetadata()
               .root_scroll_offset.value_or(default_scroll_offset)
               .y() <= 0) {
      frame_observer.WaitForMetadataChange();
    }
  }

  RenderWidgetHostImpl* GetRenderWidgetHostImpl() {
    FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
                              ->GetPrimaryFrameTree()
                              .root();
    return root->current_frame_host()->GetRenderWidgetHost();
  }
};

// Tests basic scrolling after navigating to a new origin works. Guards against
// bugs like https://crbug.com/899234 which are caused by invalid
// initialization due to the cross-origin provisional frame swap.
IN_PROC_BROWSER_TEST_P(ScrollingIntegrationTest,
                       ScrollAfterCrossOriginNavigation) {
  // Navigate to the a.com domain first.
  GURL url_domain_a(
      embedded_test_server()->GetURL("a.com", "/simple_page.html"));
  EXPECT_TRUE(NavigateToURL(shell(), url_domain_a));

  // Now navigate to baz.com, this should cause a cross-origin navigation which
  // will load into a provisional frame and then swap in as a local main frame.
  // This test ensures all the correct initialization takes place in the
  // renderer so that a basic scrolling smoke test works.
  GURL url_domain_b(embedded_test_server()->GetURL(
      "baz.com", "/scrollable_page_with_iframe.html"));
  EXPECT_TRUE(NavigateToURL(shell(), url_domain_b));
  ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));

  {
    // TODO(bokan): We currently don't have a good way to know when the
    // compositor's scrolling layers are ready after changes on the main thread.
    // We wait a timeout but that's really a hack. Fixing is tracked in
    // https://crbug.com/897520
    base::RunLoop run_loop;
    base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
        FROM_HERE, run_loop.QuitClosure(), base::Milliseconds(3000));
    run_loop.Run();
  }

  content::mojom::GestureSourceType source;

// TODO(bokan): Mac doesn't support touch events and for an unknown reason,
// Android doesn't like mouse wheel here. https://crbug.com/897520.
#if BUILDFLAG(IS_ANDROID)
  source = content::mojom::GestureSourceType::kTouchInput;
#else
  source = content::mojom::GestureSourceType::kTouchpadInput;
#endif

  // Perform the scroll (below the iframe), ensure it's correctly processed.
  DoScroll(gfx::Point(100, 110), gfx::Vector2d(0, 500), source);
  WaitForVerticalScroll();
  EXPECT_GT(GetScrollTop(), 0);
}

class SitePerProcessScrollAnchorTest : public SitePerProcessBrowserTest {
 public:
  SitePerProcessScrollAnchorTest() = default;

  void SetUpCommandLine(base::CommandLine* command_line) override {
    SitePerProcessBrowserTestBase::SetUpCommandLine(command_line);
    command_line->AppendSwitchASCII(switches::kEnableBlinkFeatures,
                                    "ScrollAnchorSerialization");
  }
};

IN_PROC_BROWSER_TEST_P(SitePerProcessScrollAnchorTest,
                       RemoteToLocalScrollAnchorRestore) {
  GURL main_url(embedded_test_server()->GetURL(
      "a.com", "/page_with_samesite_iframe.html"));
  EXPECT_TRUE(NavigateToURL(shell(), main_url));

  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
  FrameTreeNode* child = root->child_at(0);

  GURL frame_url(embedded_test_server()->GetURL("b.com", "/title1.html"));
  EXPECT_TRUE(NavigateToURLFromRenderer(child, frame_url));

  EXPECT_NE(child->current_frame_host()->GetSiteInstance(),
            root->current_frame_host()->GetSiteInstance());

  TestFrameNavigationObserver frame_observer2(child);
  EXPECT_TRUE(ExecJs(root, "window.history.back()"));
  frame_observer2.Wait();

  EXPECT_EQ(child->current_frame_host()->GetSiteInstance(),
            root->current_frame_host()->GetSiteInstance());
}

class SitePerProcessProgrammaticScrollTest : public SitePerProcessBrowserTest {
 public:
  SitePerProcessProgrammaticScrollTest()
      : kPositiveXYPlane(0, 0, kInfinity, kInfinity) {}

  SitePerProcessProgrammaticScrollTest(
      const SitePerProcessProgrammaticScrollTest&) = delete;
  SitePerProcessProgrammaticScrollTest& operator=(
      const SitePerProcessProgrammaticScrollTest&) = delete;

 protected:
  const size_t kInfinity = 1000000u;
  const std::string kIframeOutOfViewHTML = "/iframe_out_of_view.html";
  const std::string kIframeClippedHTML = "/iframe_clipped.html";
  const std::string kInputBoxHTML = "/input_box.html";
  const std::string kIframeSelector = "iframe";
  const std::string kInputSelector = "input";
  const gfx::Rect kPositiveXYPlane;

  // Waits until the |load| handle is called inside the frame.
  void WaitForOnLoad(FrameTreeNode* node) {
    RunCommandAndWaitForResponse(node, "notifyWhenLoaded();", "LOADED");
  }

  void WaitForElementVisible(FrameTreeNode* node, const std::string& sel) {
    RunCommandAndWaitForResponse(
        node,
        base::StringPrintf("notifyWhenVisible(document.querySelector('%s'));",
                           sel.c_str()),
        "VISIBLE");
  }

  void WaitForViewportToStabilize(FrameTreeNode* node) {
    RunCommandAndWaitForResponse(node, "notifyWhenViewportStable(0);",
                                 "VIEWPORT_STABLE");
  }

  void AddFocusedInputField(FrameTreeNode* node) {
    ASSERT_TRUE(ExecJs(node, "addFocusedInputField();"));
  }

  void SetWindowScroll(FrameTreeNode* node, int x, int y) {
    ASSERT_TRUE(
        ExecJs(node, base::StringPrintf("window.scrollTo(%d, %d);", x, y)));
  }

  // Helper function to retrieve the bounding client rect of the element
  // identified by |sel| inside |rfh|.
  gfx::Rect GetBoundingClientRect(RenderFrameHostImpl* rfh,
                                  const std::string& sel) {
    return GetRectFromString(
        EvalJs(rfh, JsReplace("rectAsString(document.querySelector($1)."
                              "getBoundingClientRect());",
                              sel))
            .ExtractString());
  }

  // Returns a rect representing the current |visualViewport| in the main frame
  // of |contents|.
  gfx::Rect GetVisualViewport(FrameTreeNode* node) {
    return GetRectFromString(
        EvalJs(node, "rectAsString(visualViewportAsRect());").ExtractString());
  }

  float GetVisualViewportScale(FrameTreeNode* node) {
    return EvalJs(node, "visualViewport.scale;").ExtractDouble();
  }

 private:
  void RunCommandAndWaitForResponse(FrameTreeNode* node,
                                    const std::string& command,
                                    const std::string& response) {
    ASSERT_EQ(response, EvalJs(node, command));
  }

  gfx::Rect GetRectFromString(const std::string& str) {
    std::vector<std::string> tokens = base::SplitString(
        str, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
    EXPECT_EQ(4U, tokens.size());
    double x = 0.0, y = 0.0, width = 0.0, height = 0.0;
    EXPECT_TRUE(base::StringToDouble(tokens[0], &x));
    EXPECT_TRUE(base::StringToDouble(tokens[1], &y));
    EXPECT_TRUE(base::StringToDouble(tokens[2], &width));
    EXPECT_TRUE(base::StringToDouble(tokens[3], &height));
    return {static_cast<int>(x), static_cast<int>(y), static_cast<int>(width),
            static_cast<int>(height)};
  }
};

IN_PROC_BROWSER_TEST_P(SitePerProcessProgrammaticScrollTest,
                       ScrolledOutOfView) {
  GURL main_frame(
      embedded_test_server()->GetURL("a.com", kIframeOutOfViewHTML));
  GURL child_url_b(
      embedded_test_server()->GetURL("b.com", kIframeOutOfViewHTML));

  // This will set up the page frame tree as A(B()).
  ASSERT_TRUE(NavigateToURL(shell(), main_frame));
  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
  WaitForOnLoad(root);
  EXPECT_TRUE(NavigateToURLFromRenderer(root->child_at(0), child_url_b));
  WaitForOnLoad(root->child_at(0));

  FrameTreeNode* nested_iframe_node = root->child_at(0);
  RenderFrameProxyHost* proxy_to_parent =
      nested_iframe_node->render_manager()->GetProxyToParent();
  CrossProcessFrameConnector* connector =
      proxy_to_parent->cross_process_frame_connector();

  EXPECT_TRUE(base::test::RunUntil([&]() {
    return blink::mojom::FrameVisibility::kRenderedOutOfViewport ==
           connector->visibility();
  }));
}

// This test verifies that smooth scrolling works correctly inside nested OOPIFs
// which are same origin with the parent. Note that since the frame tree has
// a A(B(A1())) structure. See https://crbug.com/865446 for more context.
IN_PROC_BROWSER_TEST_P(SitePerProcessProgrammaticScrollTest,
                       SmoothScrollInNestedSameProcessOOPIF) {
  GURL main_frame(
      embedded_test_server()->GetURL("a.com", kIframeOutOfViewHTML));
  GURL child_url_b(
      embedded_test_server()->GetURL("b.com", kIframeOutOfViewHTML));
  GURL same_origin(
      embedded_test_server()->GetURL("a.com", kIframeOutOfViewHTML));

  // This will set up the page frame tree as A(B(A1(A2()))) where A1 is later
  // asked to scroll the <iframe> element of A2 into view. The important bit
  // here is that the inner frame A1 is recursively scrolling (smoothly) an
  // element inside its document into view (A2's origin is irrelevant here).
  ASSERT_TRUE(NavigateToURL(shell(), main_frame));
  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
  WaitForOnLoad(root);
  EXPECT_TRUE(NavigateToURLFromRenderer(root->child_at(0), child_url_b));
  WaitForOnLoad(root->child_at(0));
  auto* nested_ftn = root->child_at(0)->child_at(0);
  EXPECT_TRUE(NavigateToURLFromRenderer(nested_ftn, same_origin));
  WaitForOnLoad(nested_ftn);

  // *Smoothly* scroll the inner most frame into view.
  ASSERT_TRUE(ExecJs(
      nested_ftn,
      "document.querySelector('iframe').scrollIntoView({behavior: 'smooth'})"));
  WaitForElementVisible(root, kIframeSelector);
  WaitForElementVisible(root->child_at(0), kIframeSelector);
  WaitForElementVisible(nested_ftn, kIframeSelector);
}

class ScrollObserver : public RenderWidgetHost::InputEventObserver {
 public:
  ScrollObserver(double delta_x, double delta_y) { Reset(delta_x, delta_y); }
  ~ScrollObserver() override = default;

  ScrollObserver(const ScrollObserver&) = delete;
  ScrollObserver& operator=(const ScrollObserver&) = delete;

  void OnInputEvent(const RenderWidgetHost& widget,
                    const blink::WebInputEvent& event) override {
    if (event.GetType() == blink::WebInputEvent::Type::kGestureScrollUpdate) {
      blink::WebGestureEvent received_update =
          *static_cast<const blink::WebGestureEvent*>(&event);
      remaining_delta_x_ -= received_update.data.scroll_update.delta_x;
      remaining_delta_y_ -= received_update.data.scroll_update.delta_y;
    } else if (event.GetType() ==
               blink::WebInputEvent::Type::kGestureScrollEnd) {
      if (run_loop_->running())
        run_loop_->Quit();
      DCHECK_EQ(0, remaining_delta_x_);
      DCHECK_EQ(0, remaining_delta_y_);
      scroll_end_received_ = true;
    }
  }

  void Wait() {
    if (!scroll_end_received_)
      run_loop_->Run();
  }

  void Reset(double delta_x, double delta_y) {
    run_loop_ = std::make_unique<base::RunLoop>();
    remaining_delta_x_ = delta_x;
    remaining_delta_y_ = delta_y;
    scroll_end_received_ = false;
  }

 private:
  std::unique_ptr<base::RunLoop> run_loop_;
  double remaining_delta_x_;
  double remaining_delta_y_;
  bool scroll_end_received_;
};

// Disabled for high flakiness on multiple platforms. See crbug.com/1063045
IN_PROC_BROWSER_TEST_P(SitePerProcessBrowserTest,
                       DISABLED_ScrollBubblingFromNestedOOPIFTest) {
  ui::GestureConfiguration::GetInstance()->set_scroll_debounce_interval_in_ms(
      0);
  GURL main_url(embedded_test_server()->GetURL(
      "/frame_tree/page_with_positioned_nested_frames.html"));
  EXPECT_TRUE(NavigateToURL(shell(), main_url));
  RenderFrameSubmissionObserver frame_observer(shell()->web_contents());

  // It is safe to obtain the root frame tree node here, as it doesn't change.
  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
  ASSERT_EQ(1U, root->child_count());

  FrameTreeNode* parent_iframe_node = root->child_at(0);
  GURL site_url(embedded_test_server()->GetURL(
      "a.com", "/frame_tree/page_with_positioned_frame.html"));
  EXPECT_EQ(site_url, parent_iframe_node->current_url());

  FrameTreeNode* nested_iframe_node = parent_iframe_node->child_at(0);
  GURL nested_site_url(
      embedded_test_server()->GetURL("baz.com", "/title1.html"));
  EXPECT_EQ(nested_site_url, nested_iframe_node->current_url());

  RenderWidgetHostViewBase* root_view = static_cast<RenderWidgetHostViewBase*>(
      root->current_frame_host()->GetRenderWidgetHost()->GetView());

  RenderWidgetHostViewBase* rwhv_nested =
      static_cast<RenderWidgetHostViewBase*>(
          nested_iframe_node->current_frame_host()
              ->GetRenderWidgetHost()
              ->GetView());

  WaitForHitTestData(nested_iframe_node->current_frame_host());

  InputEventAckWaiter ack_observer(
      root->current_frame_host()->GetRenderWidgetHost(),
      blink::WebInputEvent::Type::kGestureScrollBegin);

  std::unique_ptr<ScrollObserver> scroll_observer;

  // All GSU events will be wrapped between a single GSB-GSE pair. The expected
  // delta value is equal to summation of all scroll update deltas.
  scroll_observer = std::make_unique<ScrollObserver>(0, 15);

  root->current_frame_host()->GetRenderWidgetHost()->AddInputEventObserver(
      scroll_observer.get());

  // Now scroll the nested frame upward, this must bubble all the way up to the
  // root.
  blink::WebMouseWheelEvent scroll_event(
      blink::WebInputEvent::Type::kMouseWheel,
      blink::WebInputEvent::kNoModifiers,
      blink::WebInputEvent::GetStaticTimeStampForTests());
  gfx::Rect bounds = rwhv_nested->GetViewBounds();
  float scale_factor =
      frame_observer.LastRenderFrameMetadata().page_scale_factor;
  scroll_event.SetPositionInWidget(
      std::ceil((bounds.x() - root_view->GetViewBounds().x() + 10) *
                scale_factor),
      std::ceil((bounds.y() - root_view->GetViewBounds().y() + 10) *
                scale_factor));
  scroll_event.delta_units = ui::ScrollGranularity::kScrollByPrecisePixel;
  scroll_event.delta_x = 0.0f;
  scroll_event.delta_y = 5.0f;
  scroll_event.phase = blink::WebMouseWheelEvent::kPhaseBegan;
  rwhv_nested->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());
  ack_observer.Wait();

  // Send 10 wheel events with delta_y = 1 to the nested oopif.
  scroll_event.delta_y = 1.0f;
  scroll_event.phase = blink::WebMouseWheelEvent::kPhaseChanged;
  for (int i = 0; i < 10; i++)
    rwhv_nested->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());

  // Send a wheel end event to complete the scrolling sequence.
  scroll_event.delta_y = 0.0f;
  scroll_event.phase = blink::WebMouseWheelEvent::kPhaseEnded;
  rwhv_nested->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());
  scroll_observer->Wait();

  // Remove scroller_observer because it is only available in this
  // scope.
  root->current_frame_host()->GetRenderWidgetHost()->RemoveInputEventObserver(
      scroll_observer.get());
}

// Tests that scrolling bubbles from an oopif if its source body has
// "overflow:hidden" style.
IN_PROC_BROWSER_TEST_P(SitePerProcessBrowserTest,
                       ScrollBubblingFromOOPIFWithBodyOverflowHidden) {
  GURL url_domain_a(embedded_test_server()->GetURL(
      "a.com", "/scrollable_page_with_iframe.html"));
  EXPECT_TRUE(NavigateToURL(shell(), url_domain_a));
  RenderFrameSubmissionObserver frame_observer(shell()->web_contents());
  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();

  FrameTreeNode* iframe_node = root->child_at(0);
  GURL url_domain_b(
      embedded_test_server()->GetURL("b.com", "/body_overflow_hidden.html"));
  EXPECT_TRUE(NavigateToURLFromRenderer(iframe_node, url_domain_b));
  WaitForHitTestData(iframe_node->current_frame_host());

  RenderWidgetHostViewBase* root_view = static_cast<RenderWidgetHostViewBase*>(
      root->current_frame_host()->GetRenderWidgetHost()->GetView());

  RenderWidgetHostViewBase* child_view = static_cast<RenderWidgetHostViewBase*>(
      iframe_node->current_frame_host()->GetRenderWidgetHost()->GetView());

  ScrollObserver scroll_observer(0, -5);
  base::ScopedObservation<RenderWidgetHostImpl,
                          RenderWidgetHost::InputEventObserver>
      scroll_observation_(&scroll_observer);
  scroll_observation_.Observe(
      root->current_frame_host()->GetRenderWidgetHost());

  // Now scroll the nested frame downward, this must bubble to the root since
  // the iframe source body is not scrollable.
  blink::WebMouseWheelEvent scroll_event(
      blink::WebInputEvent::Type::kMouseWheel,
      blink::WebInputEvent::kNoModifiers,
      blink::WebInputEvent::GetStaticTimeStampForTests());
  gfx::Rect bounds = child_view->GetViewBounds();
  float scale_factor =
      frame_observer.LastRenderFrameMetadata().page_scale_factor;
  scroll_event.SetPositionInWidget(
      std::ceil((bounds.x() - root_view->GetViewBounds().x() + 10) *
                scale_factor),
      std::ceil((bounds.y() - root_view->GetViewBounds().y() + 10) *
                scale_factor));
  scroll_event.delta_units = ui::ScrollGranularity::kScrollByPrecisePixel;
  scroll_event.delta_x = 0.0f;
  scroll_event.delta_y = -5.0f;
  scroll_event.phase = blink::WebMouseWheelEvent::kPhaseBegan;
  child_view->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());

  // Send a wheel end event to complete the scrolling sequence.
  scroll_event.delta_y = 0.0f;
  scroll_event.phase = blink::WebMouseWheelEvent::kPhaseEnded;
  child_view->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());

  scroll_observer.Wait();
}

// Observer to navigate on scroll and wait for scroll end.
class ScrollAndNavigateObserver : public RenderWidgetHost::InputEventObserver {
 public:
  ScrollAndNavigateObserver(Shell* shell, const GURL& nav_url)
      : shell_(shell), nav_url_(nav_url) {}

  ScrollAndNavigateObserver(const ScrollAndNavigateObserver&) = delete;
  ScrollAndNavigateObserver& operator=(const ScrollAndNavigateObserver&) =
      delete;

  void OnInputEvent(const RenderWidgetHost& widget,
                    const blink::WebInputEvent& event) override {
    if (event.GetType() == blink::WebInputEvent::Type::kGestureScrollUpdate &&
        !nav_started_) {
      // Start navigation in middle of scroll.
      shell_->LoadURL(nav_url_);
      nav_started_ = true;
    } else if (event.GetType() ==
               blink::WebInputEvent::Type::kGestureScrollEnd) {
      if (run_loop_.running()) {
        run_loop_.Quit();
      }
    }
  }

  void Wait() { run_loop_.Run(); }

 private:
  raw_ptr<Shell> shell_;
  GURL nav_url_;
  bool nav_started_ = false;
  base::RunLoop run_loop_;
};

IN_PROC_BROWSER_TEST_P(SitePerProcessBrowserTest,
                       BubbledScrollEndsOnNavigationCommit) {
  GURL main_url(embedded_test_server()->GetURL(
      "a.com", "/scrollable_page_with_iframe.html"));
  EXPECT_TRUE(NavigateToURL(shell(), main_url));

  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
  FrameTreeNode* iframe_node = root->child_at(0);

  GURL child_url(
      embedded_test_server()->GetURL("b.com", "/body_overflow_hidden.html"));
  EXPECT_TRUE(NavigateToURLFromRenderer(iframe_node, child_url));
  WaitForHitTestData(iframe_node->current_frame_host());

  GURL final_url(embedded_test_server()->GetURL("c.com", "/title1.html"));

  ScrollAndNavigateObserver observer(shell(), final_url);
  base::ScopedObservation<RenderWidgetHostImpl,
                          RenderWidgetHost::InputEventObserver>
      scroll_observation_(&observer);
  scroll_observation_.Observe(
      root->current_frame_host()->GetRenderWidgetHost());

  RenderFrameSubmissionObserver frame_observer(shell()->web_contents());
  RenderWidgetHostViewBase* root_view = static_cast<RenderWidgetHostViewBase*>(
      root->current_frame_host()->GetRenderWidgetHost()->GetView());
  RenderWidgetHostViewBase* child_view = static_cast<RenderWidgetHostViewBase*>(
      iframe_node->current_frame_host()->GetRenderWidgetHost()->GetView());
  gfx::Rect bounds = child_view->GetViewBounds();
  float scale_factor =
      frame_observer.LastRenderFrameMetadata().page_scale_factor;
  gfx::PointF scroll_pos(
      std::ceil((bounds.x() - root_view->GetViewBounds().x() + 10) *
                scale_factor),
      std::ceil((bounds.y() - root_view->GetViewBounds().y() + 10) *
                scale_factor));

  SyntheticSmoothScrollGestureParams params;
  params.gesture_source_type = content::mojom::GestureSourceType::kTouchInput;
  params.anchor = scroll_pos;
  // A large scroll distance to make sure it's still active when navigation
  // starts.
  params.distances.push_back(gfx::Vector2d(0, -20000));
  params.prevent_fling = true;

  auto gesture = std::make_unique<SyntheticSmoothScrollGesture>(params);

  root->current_frame_host()->GetRenderWidgetHost()->QueueSyntheticGesture(
      std::move(gesture), base::DoNothing());

  observer.Wait();

  EXPECT_EQ(final_url, web_contents()->GetLastCommittedURL());
}

// This class intercepts RenderFrameProxyHost creations, and creates an
// SynchronizeVisualPropertiesInterceptor to intercept the message of
// SynchronizeVisualProperties. We may not use them all but we need to create
// the interceptors as soon as the RenderFrameProxyHost is created so we don't
// miss any messages.
class ScrollBubblingProxyObserver : RenderFrameProxyHost::TestObserver {
 public:
  ScrollBubblingProxyObserver() {
    RenderFrameProxyHost::SetObserverForTesting(this);
  }

  // We don't need to set an empty callback to
  // RenderFrameProxyHost::Set[Created|Deleted]CallbackForTesting because we
  // already bound callbacks using a weak ptr.
  ~ScrollBubblingProxyObserver() override {
    RenderFrameProxyHost::SetObserverForTesting(nullptr);
  }

  SynchronizeVisualPropertiesInterceptor* interceptor(
      RenderFrameProxyHost* proxy) {
    return interceptors_.find(proxy)->second.get();
  }

 private:
  void OnCreated(RenderFrameProxyHost* proxy_host) override {
    interceptors_.emplace(
        proxy_host,
        std::make_unique<SynchronizeVisualPropertiesInterceptor>(proxy_host));
  }

  void OnDeleted(RenderFrameProxyHost* proxy_host) override {
    // RenderFrameProxyHost can be deleted before the test is finished. In such
    // case, |interceptors_| should remove the mapped interceptor to avoid a
    // dangling pointer issue when it's destroyed.
    interceptors_.erase(proxy_host);
  }

  std::map<RenderFrameProxyHost*,
           std::unique_ptr<SynchronizeVisualPropertiesInterceptor>>
      interceptors_;
};

// Test that scrolling a nested out-of-process iframe bubbles unused scroll
// delta to a parent frame.
// Flaky on all platforms: https://crbug.com/1148741
IN_PROC_BROWSER_TEST_P(SitePerProcessBrowserTest,
                       DISABLED_ScrollBubblingFromOOPIFTest) {
  ScrollBubblingProxyObserver scroll_bubbling_proxy_observer;

  ui::GestureConfiguration::GetInstance()->set_scroll_debounce_interval_in_ms(
      0);
  GURL main_url(embedded_test_server()->GetURL(
      "a.com", "/cross_site_iframe_factory.html?a(b)"));
  EXPECT_TRUE(NavigateToURL(shell(), main_url));

  // It is safe to obtain the root frame tree node here, as it doesn't change.
  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
                            ->GetPrimaryFrameTree()
                            .root();
  ASSERT_EQ(1U, root->child_count());

  FrameTreeNode* parent_iframe_node = root->child_at(0);

  GURL site_url(embedded_test_server()->GetURL(
      "b.com", "/frame_tree/page_with_positioned_frame.html"));
  EXPECT_TRUE(NavigateToURLFromRenderer(parent_iframe_node, site_url));

  InputEventAckWaiter ack_observer(
      parent_iframe_node->current_frame_host()->GetRenderWidgetHost(),
      blink::WebInputEvent::Type::kGestureScrollEnd);

  // Navigate the nested frame to a page large enough to have scrollbars.
  FrameTreeNode* nested_iframe_node = parent_iframe_node->child_at(0);
  GURL nested_site_url(
      embedded_test_server()->GetURL("baz.com", "/tall_page.html"));
  EXPECT_TRUE(NavigateToURLFromRenderer(nested_iframe_node, nested_site_url));

  // This test uses the position of the nested iframe within the parent iframe
  // to infer the scroll position of the parent.
  // SynchronizeVisualPropertiesInterceptor catches updates to the position in
  // order to avoid busy waiting. It gets created early to catch the initial
  // rects from the navigation.
  RenderFrameProxyHost* parent_iframe_proxy =
      nested_iframe_node->render_manager()->GetProxyToParent();

  NavigateFrameToURL(nested_iframe_node, nested_site_url);

  EXPECT_EQ(
      " Site A ------------ proxies for B C\n"
      "   +--Site B ------- proxies for A C\n"
      "        +--Site C -- proxies for A B\n"
      "Where A = http://a.com/\n"
      "      B = http://b.com/\n"
      "      C = http://baz.com/",
      DepictFrameTree(root));

  RenderWidgetHostViewBase* rwhv_parent =
      static_cast<RenderWidgetHostViewBase*>(
          parent_iframe_node->current_frame_host()
              ->GetRenderWidgetHost()
              ->GetView());

  RenderWidgetHostViewBase* rwhv_nested =
      static_cast<RenderWidgetHostViewBase*>(
          nested_iframe_node->current_frame_host()
              ->GetRenderWidgetHost()
              ->GetView());

  WaitForHitTestData(parent_iframe_node->current_frame_host());

  auto* interceptor =
      scroll_bubbling_proxy_observer.interceptor(parent_iframe_proxy);

  // Save the original offset as a point of reference.
  interceptor->WaitForRect();
  gfx::Rect update_rect = interceptor->last_rect();
  int initial_y = update_rect.y();
  interceptor->ResetRectRunLoop();

  // Scroll the parent frame downward.
  blink::WebMouseWheelEvent scroll_event(
      blink::WebInputEvent::Type::kMouseWheel,
      blink::WebInputEvent::kNoModifiers,
      blink::WebInputEvent::GetStaticTimeStampForTests());
  scroll_event.SetPositionInWidget(1, 1);
  // Use precise pixels to keep these events off the animated scroll pathways,
  // which currently break this test.
  // https://bugs.chromium.org/p/chromium/issues/detail?id=710513
  scroll_event.delta_units = ui::ScrollGranularity::kScrollByPrecisePixel;
  scroll_event.delta_x = 0.0f;
  scroll_event.delta_y = -5.0f;
  scroll_event.phase = blink::WebMouseWheelEvent::kPhaseBegan;
  rwhv_parent->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());

  // The event router sends wheel events of a single scroll sequence to the
  // target under the first wheel event. Send a wheel end event to the current
  // target view before sending a wheel event to a different one.
  scroll_event.delta_y = 0.0f;
  scroll_event.phase = blink::WebMouseWheelEvent::kPhaseEnded;
  scroll_event.dispatch_type =
      blink::WebInputEvent::DispatchType::kEventNonBlocking;
  rwhv_parent->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());

  // Ensure that the view position is propagated to the child properly.
  interceptor->WaitForRect();
  update_rect = interceptor->last_rect();
  EXPECT_LT(update_rect.y(), initial_y);
  interceptor->ResetRectRunLoop();
  ack_observer.Reset();

  // Now scroll the nested frame upward, which should bubble to the parent.
  // The upscroll exceeds the amount that the frame was initially scrolled
  // down to account for rounding.
  scroll_event.delta_y = 6.0f;
  scroll_event.dispatch_type = blink::WebInputEvent::DispatchType::kBlocking;
  scroll_event.phase = blink::WebMouseWheelEvent::kPhaseBegan;
  rwhv_nested->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());

  interceptor->WaitForRect();
  // This loop isn't great, but it accounts for the possibility of multiple
  // incremental updates happening as a result of the scroll animation.
  // A failure condition of this test is that the loop might not terminate
  // due to bubbling not working properly. If the overscroll bubbles to the
  // parent iframe then the nested frame's y coord will return to its
  // initial position.
  update_rect = interceptor->last_rect();
  while (update_rect.y() > initial_y) {
    base::RunLoop run_loop;
    base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
        FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
    run_loop.Run();
    update_rect = interceptor->last_rect();
  }

  // The event router sends wheel events of a single scroll sequence to the
  // target under the first wheel event. Send a wheel end event to the current
  // target view before sending a wheel event to a different one.
  scroll_event.delta_y = 0.0f;
  scroll_event.phase = blink::WebMouseWheelEvent::kPhaseEnded;
  scroll_event.dispatch_type =
      blink::WebInputEvent::DispatchType::kEventNonBlocking;
  rwhv_nested->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());

  interceptor->ResetRectRunLoop();
  // Once we've sent a wheel to the nested iframe that we expect to turn into
  // a bubbling scroll, we need to delay to make sure the GestureScrollBegin
  // from this new scroll doesn't hit the RenderWidgetHostImpl before the
  // GestureScrollEnd bubbled from the child.
  // This timing only seems to be needed for CrOS, but we'll enable it on
  // all platforms just to lessen the possibility of tests being flakey
  // on non-CrOS platforms.
  ack_observer.Wait();

  // Scroll the parent down again in order to test scroll bubbling from
  // gestures.
  scroll_event.delta_y = -5.0f;
  scroll_event.dispatch_type = blink::WebInputEvent::DispatchType::kBlocking;
  scroll_event.phase = blink::WebMouseWheelEvent::kPhaseBegan;
  rwhv_parent->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());

  // The event router sends wheel events of a single scroll sequence to the
  // target under the first wheel event. Send a wheel end event to the current
  // target view before sending a wheel event to a different one.
  scroll_event.delta_y = 0.0f;
  scroll_event.phase = blink::WebMouseWheelEvent::kPhaseEnded;
  scroll_event.dispatch_type =
      blink::WebInputEvent::DispatchType::kEventNonBlocking;
  rwhv_parent->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());

  // Ensure ensuing offset change is received, and then reset the interceptor.
  interceptor->WaitForRect();
  interceptor->ResetRectRunLoop();

  // Scroll down the nested iframe via gesture. This requires 3 separate input
  // events.
  blink::WebGestureEvent gesture_event(
      blink::WebGestureEvent::Type::kGestureScrollBegin,
      blink::WebInputEvent::kNoModifiers,
      blink::WebInputEvent::GetStaticTimeStampForTests(),
      blink::WebGestureDevice::kTouchpad);
  gesture_event.SetPositionInWidget(gfx::PointF(1, 1));
  gesture_event.data.scroll_begin.delta_x_hint = 0.0f;
  gesture_event.data.scroll_begin.delta_y_hint = 6.0f;
  rwhv_nested->GetRenderWidgetHost()->ForwardGestureEvent(gesture_event);

  gesture_event =
      blink::WebGestureEvent(blink::WebGestureEvent::Type::kGestureScrollUpdate,
                             blink::WebInputEvent::kNoModifiers,
                             blink::WebInputEvent::GetStaticTimeStampForTests(),
                             blink::WebGestureDevice::kTouchpad);
  gesture_event.SetPositionInWidget(gfx::PointF(1, 1));
  gesture_event.data.scroll_update.delta_x = 0.0f;
  gesture_event.data.scroll_update.delta_y = 6.0f;
  rwhv_nested->GetRenderWidgetHost()->ForwardGestureEvent(gesture_event);

  gesture_event =
      blink::WebGestureEvent(blink::WebGestureEvent::Type::kGestureScrollEnd,
                             blink::WebInputEvent::kNoModifiers,
                             blink::WebInputEvent::GetStaticTimeStampForTests(),
                             blink::WebGestureDevice::kTouchpad);
  gesture_event.SetPositionInWidget(gfx::PointF(1, 1));
  rwhv_nested->GetRenderWidgetHost()->ForwardGestureEvent(gesture_event);

  interceptor->WaitForRect();
  update_rect = interceptor->last_rect();
  // As above, if this loop does not terminate then it indicates an issue
  // with scroll bubbling.
  while (update_rect.y() > initial_y) {
    base::RunLoop run_loop;
    base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
        FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
    run_loop.Run();
    update_rect = interceptor->last_rect();
  }

  // Test that when the child frame absorbs all of the scroll delta, it does
  // not propagate to the parent (see https://crbug.com/621624).
  interceptor->ResetRectRunLoop();
  scroll_event.delta_y = -5.0f;
  scroll_event.dispatch_type = blink::WebInputEvent::DispatchType::kBlocking;
  scroll_event.phase = blink::WebMouseWheelEvent::kPhaseBegan;
  rwhv_nested->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());
  // It isn't possible to busy loop waiting on the renderer here because we
  // are explicitly testing that something does *not* happen. This creates a
  // small chance of false positives but shouldn't result in false negatives,
  // so flakiness implies this test is failing.
  {
    base::RunLoop run_loop;
    base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
        FROM_HERE, run_loop.QuitClosure(), TestTimeouts::action_timeout());
    run_loop.Run();
  }
  DCHECK_EQ(interceptor->last_rect().x(), 0);
  DCHECK_EQ(interceptor->last_rect().y(), 0);
}

// Tests that scrolling with the keyboard will bubble unused scroll to the
// OOPIF's parent.
// Disabled on Android due to flakes; see b/338341090.
#if BUILDFLAG(IS_ANDROID)
#define MAYBE_KeyboardScrollBubblingFromOOPIF \
  DISABLED_KeyboardScrollBubblingFromOOPIF
#else
#define MAYBE_KeyboardScrollBubblingFromOOPIF KeyboardScrollBubblingFromOOPIF
#endif
IN_PROC_BROWSER_TEST_P(SitePerProcessBrowserTest,
                       MAYBE_KeyboardScrollBubblingFromOOPIF) {
  GURL main_url(embedded_test_server()->GetURL(
      "a.com", "/frame_tree/page_with_iframe_in_scrollable_div.html"));
  EXPECT_TRUE(NavigateToURL(shell(), main_url));

  // It is safe to obtain the root frame tree node here, as it doesn't change.
  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
                            ->GetPrimaryFrameTree()
                            .root();
  ASSERT_EQ(1U, root->child_count());

  FrameTreeNode* iframe_node = root->child_at(0);

  EXPECT_EQ(
      " Site A ------------ proxies for B\n"
      "   +--Site B ------- proxies for A\n"
      "Where A = http://a.com/\n"
      "      B = http://b.com/",
      DepictFrameTree(root));

  RenderWidgetHostViewBase* rwhv_child = static_cast<RenderWidgetHostViewBase*>(
      iframe_node->current_frame_host()->GetRenderWidgetHost()->GetView());

  // This test does not involve hit testing, but input events could be dropped
  // by the renderer before the first compositor commit, so we wait here anyway
  // to avoid that.
  WaitForHitTestData(iframe_node->current_frame_host());

  EXPECT_DOUBLE_EQ(
      0.0,
      EvalJs(root,
             "var wrapperDiv = document.getElementById('wrapper-div');"
             "var initial_y = wrapperDiv.scrollTop;"
             "var waitForScrollDownPromise = new Promise(function(resolve) {"
             "  wrapperDiv.addEventListener('scroll', () => {"
             "    if (wrapperDiv.scrollTop > initial_y)"
             "      resolve(wrapperDiv.scrollTop);"
             "  });"
             "});"
             "initial_y;")
          .ExtractDouble());

  input::NativeWebKeyboardEvent key_event(
      blink::WebKeyboardEvent::Type::kRawKeyDown,
      blink::WebInputEvent::kNoModifiers,
      blink::WebInputEvent::GetStaticTimeStampForTests());
  key_event.windows_key_code = ui::VKEY_DOWN;
  key_event.native_key_code =
      ui::KeycodeConverter::DomCodeToNativeKeycode(ui::DomCode::ARROW_DOWN);
  key_event.dom_code = static_cast<int>(ui::DomCode::ARROW_DOWN);
  key_event.dom_key = ui::DomKey::ARROW_DOWN;

  rwhv_child->GetRenderWidgetHost()->ForwardKeyboardEvent(key_event);

  key_event.SetType(blink::WebKeyboardEvent::Type::kKeyUp);
  rwhv_child->GetRenderWidgetHost()->ForwardKeyboardEvent(key_event);

  double scrolled_y = EvalJs(root, "waitForScrollDownPromise").ExtractDouble();
  EXPECT_GT(scrolled_y, 0.0);
}

// Ensure that the scrollability of a local subframe in an OOPIF is considered
// when acknowledging GestureScrollBegin events sent to OOPIFs.
IN_PROC_BROWSER_TEST_P(SitePerProcessBrowserTest, ScrollLocalSubframeInOOPIF) {
  ui::GestureConfiguration::GetInstance()->set_scroll_debounce_interval_in_ms(
      0);

  // This must be tall enough such that the outer iframe is not scrollable.
  GURL main_url(embedded_test_server()->GetURL(
      "a.com", "/frame_tree/page_with_tall_positioned_frame.html"));
  EXPECT_TRUE(NavigateToURL(shell(), main_url));

  // It is safe to obtain the root frame tree node here, as it doesn't change.
  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
  ASSERT_EQ(1U, root->child_count());

  FrameTreeNode* parent_iframe_node = root->child_at(0);
  GURL outer_frame_url(embedded_test_server()->GetURL(
      "baz.com", "/frame_tree/page_with_positioned_frame.html"));
  EXPECT_TRUE(NavigateToURLFromRenderer(parent_iframe_node, outer_frame_url));

  // This must be tall enough such that the inner iframe is scrollable.
  FrameTreeNode* nested_iframe_node = parent_iframe_node->child_at(0);
  GURL inner_frame_url(
      embedded_test_server()->GetURL("baz.com", "/tall_page.html"));
  EXPECT_TRUE(NavigateToURLFromRenderer(nested_iframe_node, inner_frame_url));

  ASSERT_EQ(
      " Site A ------------ proxies for B\n"
      "   +--Site B ------- proxies for A\n"
      "        +--Site B -- proxies for A\n"
      "Where A = http://a.com/\n"
      "      B = http://baz.com/",
      DepictFrameTree(root));

  RenderWidgetHostViewBase* rwhv_child = static_cast<RenderWidgetHostViewBase*>(
      nested_iframe_node->current_frame_host()
          ->GetRenderWidgetHost()
          ->GetView());

  WaitForHitTestData(parent_iframe_node->current_frame_host());

  // When we scroll the inner frame, we should have the GSB be consumed.
  // The outer iframe not being scrollable should not cause the GSB to go
  // unconsumed.
  InputEventAckWaiter ack_observer(
      parent_iframe_node->current_frame_host()->GetRenderWidgetHost(),
      base::BindRepeating([](blink::mojom::InputEventResultSource,
                             blink::mojom::InputEventResultState state,
                             const blink::WebInputEvent& event) {
        return event.GetType() ==
                   blink::WebGestureEvent::Type::kGestureScrollBegin &&
               state == blink::mojom::InputEventResultState::kConsumed;
      }));

  // Wait until renderer's compositor thread is synced. Otherwise the non fast
  // scrollable regions won't be set when the event arrives.
  MainThreadFrameObserver observer(rwhv_child->GetRenderWidgetHost());
  observer.Wait();

  // Now scroll the inner frame downward.
  blink::WebMouseWheelEvent scroll_event(
      blink::WebInputEvent::Type::kMouseWheel,
      blink::WebInputEvent::kNoModifiers,
      blink::WebInputEvent::GetStaticTimeStampForTests());
  scroll_event.SetPositionInWidget(90, 110);
  scroll_event.delta_units = ui::ScrollGranularity::kScrollByPrecisePixel;
  scroll_event.delta_x = 0.0f;
  scroll_event.delta_y = -50.0f;
  scroll_event.phase = blink::WebMouseWheelEvent::kPhaseBegan;
  rwhv_child->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());
  ack_observer.Wait();
}

class OOPIFScrollBubblingTest : public SitePerProcessBrowserTest {
 public:
  OOPIFScrollBubblingTest() {
    scoped_feature_list_.InitWithFeatureState(
        blink::features::kAsyncTouchMovesImmediatelyAfterScroll,
        /* enabled= */ true);
  }
  ~OOPIFScrollBubblingTest() override = default;

 private:
  base::test::ScopedFeatureList scoped_feature_list_;
};

class TouchMoveInjectingObserver : public RenderWidgetHost::InputEventObserver {
 public:
  TouchMoveInjectingObserver(
      RenderWidgetHost* target_widget,
      base::WeakPtr<SyntheticGestureController> synthetic_gesture_controller,
      base::RunLoop* run_loop)
      : target_rwh_(static_cast<RenderWidgetHostImpl*>(target_widget)),
        gesture_controller_(synthetic_gesture_controller),
        run_loop_(run_loop) {}

  TouchMoveInjectingObserver(const TouchMoveInjectingObserver&) = delete;
  TouchMoveInjectingObserver& operator=(const TouchMoveInjectingObserver&) =
      delete;

  void OnInputEvent(const RenderWidgetHost& widget,
                    const blink::WebInputEvent& event) override {
    const RenderWidgetHostViewBase* view =
        static_cast<const RenderWidgetHostViewBase*>(widget.GetView());
    bool is_child_view = view->IsRenderWidgetHostViewChildFrame();
    if (is_child_view) {
      OnInputEventOnChildFrame(event);
      return;
    }
    OnInputEventOnRootFrame(event);
  }

  bool root_view_has_seen_gsu_for_async_touch_move() const {
    return root_view_has_seen_gsu_for_async_touch_move_;
  }

 private:
  void OnInputEventOnChildFrame(const blink::WebInputEvent& event) {
    if (event.GetType() == blink::WebInputEvent::Type::kGestureScrollBegin) {
      GetUIThreadTaskRunner({BrowserTaskType::kUserInput})
          ->PostTask(FROM_HERE, base::BindOnce(
                                    [](base::WeakPtr<SyntheticGestureController>
                                           gesture_controller) {
                                      if (!gesture_controller) {
                                        return;
                                      }
                                      gesture_controller->DispatchNextEvent(
                                          base::TimeTicks::Now());
                                    },
                                    gesture_controller_));
      has_seen_gesture_scroll_begin_ = true;
      return;
    }
    if (event.GetType() == blink::WebInputEvent::Type::kTouchMove &&
        has_seen_gesture_scroll_begin_ &&
        first_touch_move_after_scroll_begin_id_ == -1) {
      first_touch_move_after_scroll_begin_id_ =
          static_cast<const blink::WebTouchEvent&>(event).unique_touch_event_id;
      return;
    }
  }

  void OnInputEventOnRootFrame(const blink::WebInputEvent& event) {
    if (event.GetType() != blink::WebInputEvent::Type::kGestureScrollUpdate) {
      return;
    }
    const blink::WebGestureEvent& gesture_event =
        static_cast<const blink::WebGestureEvent&>(event);
    if (gesture_event.unique_touch_event_id ==
        first_touch_move_after_scroll_begin_id_) {
      ASSERT_FALSE(root_view_has_seen_gsu_for_async_touch_move_);
      root_view_has_seen_gsu_for_async_touch_move_ = true;
      run_loop_->Quit();
    }
  }
  int first_touch_move_after_scroll_begin_id_ = -1;
  bool root_view_has_seen_gsu_for_async_touch_move_ = false;
  bool has_seen_gesture_scroll_begin_ = false;
  raw_ptr<RenderWidgetHostImpl> target_rwh_;
  base::WeakPtr<SyntheticGestureController> gesture_controller_;
  raw_ptr<base::RunLoop> run_loop_;
};

IN_PROC_BROWSER_TEST_P(OOPIFScrollBubblingTest,
                       ScrollBubblingWithTouchMoveInjection) {
  GURL main_url(embedded_test_server()->GetURL(
      "a.com", "/scrollable_page_with_iframe.html"));
  EXPECT_TRUE(NavigateToURL(shell(), main_url));
  RenderFrameSubmissionObserver frame_observer(shell()->web_contents());

  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
  RenderWidgetHostImpl* root_rwh =
      root->current_frame_host()->GetRenderWidgetHost();
  RenderWidgetHostViewBase* root_view =
      static_cast<RenderWidgetHostViewBase*>(root_rwh->GetView());

  FrameTreeNode* iframe_node = root->child_at(0);
  GURL url_domain_b(embedded_test_server()->GetURL(
      "b.com", "/body_overflow_hidden_blocking_touch_handlers.html"));
  EXPECT_TRUE(NavigateToURLFromRenderer(iframe_node, url_domain_b));
  WaitForHitTestData(iframe_node->current_frame_host());
  RenderWidgetHostImpl* iframe_rwh =
      iframe_node->current_frame_host()->GetRenderWidgetHost();

  gfx::Rect iframe_bounds =
      iframe_node->current_frame_host()->GetView()->GetViewBounds();
  float scale_factor =
      frame_observer.LastRenderFrameMetadata().page_scale_factor;
  gfx::PointF scroll_pos(
      std::ceil((iframe_bounds.x() - root_view->GetViewBounds().x() + 10) *
                scale_factor),
      std::ceil((iframe_bounds.y() - root_view->GetViewBounds().y() + 10) *
                scale_factor));

  SyntheticSmoothScrollGestureParams params;
  params.gesture_source_type = content::mojom::GestureSourceType::kTouchInput;
  params.anchor = scroll_pos;
  params.distances.push_back(gfx::Vector2d(0, -200));  // Scroll down.
  params.granularity = ui::ScrollGranularity::kScrollByPrecisePixel;

  auto gesture = std::make_unique<SyntheticSmoothScrollGesture>(params);

  base::RunLoop run_loop;
  root_rwh->CreateSyntheticGestureControllerIfNecessary();
  root_rwh->SyntheticGestureControllerForTesting()
      ->SetRendererInitializedForTesting(true);
  root_rwh->QueueSyntheticGesture(std::move(gesture), base::DoNothing());

  TouchMoveInjectingObserver observer(
      iframe_rwh,
      root_rwh->SyntheticGestureControllerForTesting()->GetWeakPtr(),
      &run_loop);

  root->current_frame_host()->GetRenderWidgetHost()->AddInputEventObserver(
      &observer);
  iframe_rwh->AddInputEventObserver(&observer);
  run_loop.Run();

  EXPECT_TRUE(observer.root_view_has_seen_gsu_for_async_touch_move());

  root->current_frame_host()->GetRenderWidgetHost()->RemoveInputEventObserver(
      &observer);
  iframe_rwh->RemoveInputEventObserver(&observer);
}

INSTANTIATE_TEST_SUITE_P(All,
                         ScrollingIntegrationTest,
                         testing::ValuesIn(RenderDocumentFeatureLevelValues()));
INSTANTIATE_TEST_SUITE_P(All,
                         OOPIFScrollBubblingTest,
                         testing::ValuesIn(RenderDocumentFeatureLevelValues()));
INSTANTIATE_TEST_SUITE_P(All,
                         SitePerProcessScrollAnchorTest,
                         testing::ValuesIn(RenderDocumentFeatureLevelValues()));
INSTANTIATE_TEST_SUITE_P(All,
                         SitePerProcessProgrammaticScrollTest,
                         testing::ValuesIn(RenderDocumentFeatureLevelValues()));

}  // namespace content
