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

#include "content/browser/find_request_manager.h"

#include "base/command_line.h"
#include "base/memory/raw_ptr.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "content/browser/find_in_page_client.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/back_forward_cache_util.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_content_browser_client.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/fenced_frame_test_util.h"
#include "content/public/test/find_test_utils.h"
#include "content/public/test/no_renderer_crashes_assertion.h"
#include "content/public/test/prerender_test_util.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test_utils_internal.h"
#include "net/dns/mock_host_resolver.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/web_preferences/web_preferences.h"
#include "third_party/blink/public/mojom/page/widget.mojom-test-utils.h"
#include "url/origin.h"

#if BUILDFLAG(IS_ANDROID)
#include "ui/android/view_android.h"
#endif

namespace content {

namespace {

const int kInvalidId = -1;

const url::Origin& GetOriginForFrameTreeNode(FrameTreeNode* node) {
  return node->current_frame_host()->GetLastCommittedOrigin();
}

#if BUILDFLAG(IS_ANDROID)
double GetFrameDeviceScaleFactor(const ToRenderFrameHost& adapter) {
  return EvalJs(adapter, "window.devicePixelRatio;").ExtractDouble();
}
#endif  // BUILDFLAG(IS_ANDROID)

}  // namespace

class FindRequestManagerTestBase : public ContentBrowserTest {
 public:
  FindRequestManagerTestBase()
      : normal_delegate_(nullptr), last_request_id_(0) {}

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

  ~FindRequestManagerTestBase() override = default;

  void SetUpOnMainThread() override {
    host_resolver()->AddRule("*", "127.0.0.1");
    ASSERT_TRUE(embedded_test_server()->Start());

    // Swap the WebContents's delegate for our test delegate.
    normal_delegate_ = contents()->GetDelegate();
    contents()->SetDelegate(&test_delegate_);
  }

  void TearDownOnMainThread() override {
    // Swap the WebContents's delegate back to its usual delegate.
    contents()->SetDelegate(normal_delegate_);
    normal_delegate_ = nullptr;
  }

  void SetUpCommandLine(base::CommandLine* command_line) override {
    IsolateAllSitesForTesting(command_line);
  }

 protected:
  // Navigates to |url| and waits for it to finish loading.
  void LoadAndWait(const std::string& url) {
    TestNavigationObserver navigation_observer(contents());
    EXPECT_TRUE(
        NavigateToURL(shell(), embedded_test_server()->GetURL("a.com", url)));
    ASSERT_TRUE(navigation_observer.last_navigation_succeeded());

    // crbug.com/330147459: Ensure a frame has been produced in the renderer so
    // the active match is set correctly.
    ASSERT_TRUE(
        EvalJsAfterLifecycleUpdate(contents()->GetPrimaryMainFrame(), "", "")
            .is_ok());
  }

  // Loads a multi-frame page. The page will have a full binary frame tree of
  // height |height|. If |cross_process| is true, child frames will be loaded
  // cross-process.
  void LoadMultiFramePage(int height, bool cross_process) {
    LoadAndWait("/find_in_page_multi_frame.html");
    LoadMultiFramePageChildFrames(height, cross_process, root());
  }

  // Reloads the child frame cross-process.
  void MakeChildFrameCrossProcess() {
    FrameTreeNode* child = first_child();
    GURL url =
        embedded_test_server()->GetURL("b.com", child->current_url().GetPath());
    EXPECT_TRUE(NavigateToURLFromRenderer(child, url));
  }

  void Find(const std::string& search_text,
            blink::mojom::FindOptionsPtr options) {
    delegate()->UpdateLastRequest(++last_request_id_);
    contents()->Find(last_request_id_, base::UTF8ToUTF16(search_text),
                     std::move(options), /*skip_delay=*/false);
  }

  WebContentsImpl* contents() const {
    return static_cast<WebContentsImpl*>(shell()->web_contents());
  }

  FindTestWebContentsDelegate* delegate() const {
    return static_cast<FindTestWebContentsDelegate*>(contents()->GetDelegate());
  }

  int last_request_id() const {
    return last_request_id_;
  }

  FrameTreeNode* root() { return contents()->GetPrimaryFrameTree().root(); }

  FrameTreeNode* first_child() { return root()->child_at(0); }

 private:
  // Helper function for LoadMultiFramePage. Loads child frames until the frame
  // tree rooted at |root| is a full binary tree of height |height|.
  void LoadMultiFramePageChildFrames(int height,
                                     bool cross_process,
                                     FrameTreeNode* root) {
    if (height == 0)
      return;

    std::string hostname = root->current_origin().host();
    if (cross_process)
      hostname.insert(0, 1, 'a');
    GURL url(embedded_test_server()->GetURL(hostname,
                                            "/find_in_page_multi_frame.html"));

    TestNavigationObserver observer(shell()->web_contents());

    FrameTreeNode* child = root->child_at(0);
    NavigateFrameToURL(child, url);
    EXPECT_TRUE(observer.last_navigation_succeeded());
    LoadMultiFramePageChildFrames(height - 1, cross_process, child);

    child = root->child_at(1);
    NavigateFrameToURL(child, url);
    EXPECT_TRUE(observer.last_navigation_succeeded());
    LoadMultiFramePageChildFrames(height - 1, cross_process, child);
  }

  FindTestWebContentsDelegate test_delegate_;
  raw_ptr<WebContentsDelegate> normal_delegate_;

  // The ID of the last find request requested.
  int last_request_id_;
};

class FindRequestManagerTest : public FindRequestManagerTestBase,
                               public testing::WithParamInterface<bool> {
 protected:
  bool test_with_oopif() const { return GetParam(); }
};

INSTANTIATE_TEST_SUITE_P(FindRequestManagerTests,
                         FindRequestManagerTest,
                         testing::Bool());

// TODO(crbug.com/40470937): These tests frequently fail on Android.
#if BUILDFLAG(IS_ANDROID)
#define MAYBE(x) DISABLED_##x
#else
#define MAYBE(x) x
#endif


// Tests basic find-in-page functionality (such as searching forward and
// backward) and check for correct results at each step.
IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, MAYBE(Basic)) {
  LoadAndWait("/find_in_page.html");
  if (test_with_oopif())
    MakeChildFrameCrossProcess();

  auto options = blink::mojom::FindOptions::New();
  options->run_synchronously_for_testing = true;
  Find("result", options->Clone());
  delegate()->WaitForFinalReply();

  FindResults results = delegate()->GetFindResults();
  EXPECT_EQ(last_request_id(), results.request_id);
  EXPECT_EQ(19, results.number_of_matches);
  EXPECT_EQ(1, results.active_match_ordinal);

  options->new_session = false;
  for (int i = 2; i <= 10; ++i) {
    Find("result", options->Clone());
    delegate()->WaitForFinalReply();

    results = delegate()->GetFindResults();
    EXPECT_EQ(last_request_id(), results.request_id);
    EXPECT_EQ(19, results.number_of_matches);
    EXPECT_EQ(i, results.active_match_ordinal);
  }

  options->forward = false;
  for (int i = 9; i >= 5; --i) {
    Find("result", options->Clone());
    delegate()->WaitForFinalReply();

    results = delegate()->GetFindResults();
    EXPECT_EQ(last_request_id(), results.request_id);
    EXPECT_EQ(19, results.number_of_matches);
    EXPECT_EQ(i, results.active_match_ordinal);
  }
}

IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, FindInPage_Issue615291) {
  LoadAndWait("/find_in_simple_page.html");

  auto options = blink::mojom::FindOptions::New();
  options->run_synchronously_for_testing = true;
  options->find_match = false;
  Find("result", options->Clone());
  delegate()->WaitForFinalReply();

  FindResults results = delegate()->GetFindResults();
  EXPECT_EQ(5, results.number_of_matches);
  EXPECT_EQ(0, results.active_match_ordinal);

  options->new_session = false;
  Find("result", options->Clone());
  // With the issue being tested, this would loop forever and cause the
  // test to timeout.
  delegate()->WaitForFinalReply();
  results = delegate()->GetFindResults();
  EXPECT_EQ(5, results.number_of_matches);
  EXPECT_EQ(0, results.active_match_ordinal);
}

bool ExecuteScriptAndExtractRect(FrameTreeNode* frame,
                                 const std::string& script,
                                 gfx::Rect* out) {
  std::string script_and_extract =
      script + "rect.x + ',' + rect.y + ',' + rect.width + ',' + rect.height;";
  std::string result = EvalJs(frame, script_and_extract).ExtractString();

  std::vector<std::string> tokens = base::SplitString(
      result, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  if (tokens.size() != 4U)
    return false;

  double x, y, width, height;
  if (!base::StringToDouble(tokens[0], &x) ||
      !base::StringToDouble(tokens[1], &y) ||
      !base::StringToDouble(tokens[2], &width) ||
      !base::StringToDouble(tokens[3], &height))
    return false;

  *out = gfx::Rect(static_cast<int>(x), static_cast<int>(y),
                   static_cast<int>(width), static_cast<int>(height));
  return true;
}

// Basic test that a search result is actually brought into view.
IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, ScrollAndZoomIntoView) {
  WebContentsImpl* web_contents =
      static_cast<WebContentsImpl*>(shell()->web_contents());
  blink::web_pref::WebPreferences prefs =
      web_contents->GetOrCreateWebPreferences();
  prefs.smooth_scroll_for_find_enabled = false;
  web_contents->SetWebPreferences(prefs);

  LoadAndWait("/find_in_page_desktop.html");
  // Note: for now, don't run this test on Android in OOPIF mode.
  if (test_with_oopif())
#if BUILDFLAG(IS_ANDROID)
    return;
#else
    MakeChildFrameCrossProcess();
#endif  // BUILDFLAG(IS_ANDROID)

  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
                            ->GetPrimaryFrameTree()
                            .root();
  FrameTreeNode* child = root->child_at(0);

  // Start off at a non-origin scroll offset to ensure coordinate conversisons
  // work correctly.
  ASSERT_TRUE(ExecJs(root, "window.scrollTo(3500, 1500);"));

  // Search for a result further down in the iframe.
  auto options = blink::mojom::FindOptions::New();
  options->run_synchronously_for_testing = true;
  Find("result 17", options->Clone());
  delegate()->WaitForFinalReply();

  // gBCR of result box in iframe.
  gfx::Rect target_in_iframe;

  // gBCR of iframe in main document.
  gfx::Rect iframe_rect;

  // Window size with location at origin (for comparison with gBCR).
  gfx::Rect root_rect;

  // Visual viewport rect relative to root_rect.
  gfx::Rect visual_rect;

  ASSERT_TRUE(ExecuteScriptAndExtractRect(
      child,
      "var result = document.querySelector('.margin-overflow');"
      "var rect = result.getBoundingClientRect();",
      &target_in_iframe));
  ASSERT_TRUE(ExecuteScriptAndExtractRect(
      root,
      "var rect = document.querySelector('#frame').getBoundingClientRect();",
      &iframe_rect));
  ASSERT_TRUE(ExecuteScriptAndExtractRect(
      root,
      "var rect = new DOMRect(0, 0, window.innerWidth, window.innerHeight);",
      &root_rect));
  ASSERT_TRUE(ExecuteScriptAndExtractRect(
      root,
      "var rect = new DOMRect(visualViewport.offsetLeft, "
      "                       visualViewport.offsetTop,"
      "                       visualViewport.width,"
      "                       visualViewport.height);",
      &visual_rect));

  gfx::Rect result_in_root = target_in_iframe + iframe_rect.OffsetFromOrigin();

  EXPECT_TRUE(gfx::Rect(iframe_rect.size()).Contains(target_in_iframe))
      << "Result rect[ " << target_in_iframe.ToString()
      << " ] not visible in iframe [ 0,0 " << iframe_rect.size().ToString()
      << " ].";

  EXPECT_TRUE(root_rect.Contains(result_in_root))
      << "Result rect[ " << result_in_root.ToString()
      << " ] not visible in root frame [ " << root_rect.ToString() << " ].";

  EXPECT_TRUE(visual_rect.Contains(result_in_root))
      << "Result rect[ " << result_in_root.ToString()
      << " ] not visible in visual viewport [ " << visual_rect.ToString()
      << " ].";
}

// Tests searching for a word character-by-character, as would typically be done
// by a user typing into the find bar.
IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, MAYBE(CharacterByCharacter)) {
  LoadAndWait("/find_in_page.html");
  if (test_with_oopif())
    MakeChildFrameCrossProcess();

  auto default_options = blink::mojom::FindOptions::New();
  default_options->run_synchronously_for_testing = true;
  Find("r", default_options->Clone());
  Find("re", default_options->Clone());
  Find("res", default_options->Clone());
  Find("resu", default_options->Clone());
  Find("resul", default_options->Clone());
  Find("result", default_options->Clone());
  delegate()->WaitForFinalReply();

  FindResults results = delegate()->GetFindResults();
  EXPECT_EQ(last_request_id(), results.request_id);
  EXPECT_EQ(19, results.number_of_matches);
  EXPECT_EQ(1, results.active_match_ordinal);
}

// TODO(crbug.com/40470937): This test frequently fails on Android.
// TODO(crbug.com/41291496): This test is flaky on Win
// TODO(crbug.com/41393143): Flaky on CrOS MSan
// Tests sending a large number of find requests subsequently.
IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, DISABLED_RapidFire) {
  LoadAndWait("/find_in_page.html");
  if (test_with_oopif())
    MakeChildFrameCrossProcess();

  auto options = blink::mojom::FindOptions::New();
  options->run_synchronously_for_testing = true;
  Find("result", options.Clone());

  options->new_session = false;
  for (int i = 2; i <= 1000; ++i)
    Find("result", options.Clone());
  delegate()->WaitForFinalReply();

  FindResults results = delegate()->GetFindResults();
  EXPECT_EQ(last_request_id(), results.request_id);
  EXPECT_EQ(19, results.number_of_matches);
  EXPECT_EQ(last_request_id() % results.number_of_matches,
            results.active_match_ordinal);
}

// Tests removing a frame during a find session.
// TODO(crbug.com/40489609): Test is flaky on all platforms.
IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, DISABLED_RemoveFrame) {
  LoadMultiFramePage(2 /* height */, test_with_oopif() /* cross_process */);

  auto options = blink::mojom::FindOptions::New();
  options->run_synchronously_for_testing = true;
  Find("result", options->Clone());
  delegate()->WaitForFinalReply();
  options->new_session = false;
  options->forward = false;
  Find("result", options->Clone());
  Find("result", options->Clone());
  Find("result", options->Clone());
  Find("result", options->Clone());
  Find("result", options->Clone());
  delegate()->WaitForFinalReply();

  FindResults results = delegate()->GetFindResults();
  EXPECT_EQ(last_request_id(), results.request_id);
  EXPECT_EQ(21, results.number_of_matches);
  EXPECT_EQ(17, results.active_match_ordinal);

  // Remove a frame.
  root()->current_frame_host()->RemoveChild(first_child());

  // The number of matches and active match ordinal should update automatically
  // to exclude the matches from the removed frame.
  results = delegate()->GetFindResults();
  EXPECT_EQ(12, results.number_of_matches);
  EXPECT_EQ(8, results.active_match_ordinal);
}

IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, RemoveMainFrame) {
  LoadAndWait("/find_in_page.html");

  auto options = blink::mojom::FindOptions::New();
  options->run_synchronously_for_testing = true;
  Find("result", options->Clone());
  delegate()->WaitForFinalReply();
  options->new_session = false;
  options->forward = false;
  Find("result", options->Clone());
  Find("result", options->Clone());
  Find("result", options->Clone());
  Find("result", options->Clone());
  Find("result", options->Clone());

  // Don't wait for the reply, and end the test. This will remove the main
  // frame, which should not crash.
}

// Tests adding a frame during a find session.
// TODO(crbug.com/40489609): Test is flaky on all platforms.
IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, DISABLED_AddFrame) {
  LoadMultiFramePage(2 /* height */, test_with_oopif() /* cross_process */);

  auto options = blink::mojom::FindOptions::New();
  options->run_synchronously_for_testing = true;
  Find("result", options.Clone());
  options->new_session = false;
  Find("result", options.Clone());
  Find("result", options.Clone());
  Find("result", options.Clone());
  Find("result", options.Clone());
  delegate()->WaitForFinalReply();

  FindResults results = delegate()->GetFindResults();
  EXPECT_EQ(last_request_id(), results.request_id);
  EXPECT_EQ(21, results.number_of_matches);
  EXPECT_EQ(5, results.active_match_ordinal);

  // Add a frame. It contains 5 new matches.
  std::string url = embedded_test_server()
                        ->GetURL(test_with_oopif() ? "b.com" : "a.com",
                                 "/find_in_simple_page.html")
                        .spec();
  std::string script = std::string() +
      "var frame = document.createElement('iframe');" +
      "frame.src = '" + url + "';" +
      "document.body.appendChild(frame);";
  delegate()->MarkNextReply();
  ASSERT_TRUE(ExecJs(shell(), script));
  delegate()->WaitForNextReply();

  // The number of matches should update automatically to include the matches
  // from the newly added frame.
  results = delegate()->GetFindResults();
  EXPECT_EQ(26, results.number_of_matches);
  EXPECT_EQ(5, results.active_match_ordinal);
}

// Tests adding an in-process hidden iframe during a find session.
IN_PROC_BROWSER_TEST_P(FindRequestManagerTest,
                       AddInprocessHiddenFrameDuringFind) {
  LoadAndWait("/find_in_page.html");

  auto options = blink::mojom::FindOptions::New();
  options->run_synchronously_for_testing = true;
  Find("result", options.Clone());
  delegate()->WaitForFinalReply();

  FindResults results = delegate()->GetFindResults();
  EXPECT_EQ(19, results.number_of_matches);

  // Add a frame. It contains 5 new matches.
  std::string url = embedded_test_server()
                        ->GetURL("a.com", "/find_in_simple_page.html")
                        .spec();
  std::string script = JsReplace(R"JS(
      var frame = document.createElement('iframe');
      frame.src = '$1';
      frame.style.visibility = 'hidden';
      document.body.appendChild(frame);
      )JS",
                                 url);

  delegate()->MarkNextReply();
  ASSERT_TRUE(ExecJs(shell(), script));
  delegate()->WaitForNextReply();

  // The number of matches should not be effected by the
  // the newly added hidden frame.
  results = delegate()->GetFindResults();
  EXPECT_EQ(19, results.number_of_matches);
}

// Tests adding a frame during a find session where there were previously no
// matches.
IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, MAYBE(AddFrameAfterNoMatches)) {
  TestNavigationObserver navigation_observer(contents());
  EXPECT_TRUE(NavigateToURL(shell(), GURL("about:blank")));
  EXPECT_TRUE(navigation_observer.last_navigation_succeeded());

  auto default_options = blink::mojom::FindOptions::New();
  default_options->run_synchronously_for_testing = true;
  Find("result", default_options.Clone());
  delegate()->WaitForFinalReply();

  // Initially, there are no matches on the page.
  FindResults results = delegate()->GetFindResults();
  EXPECT_EQ(last_request_id(), results.request_id);
  EXPECT_EQ(0, results.number_of_matches);
  EXPECT_EQ(0, results.active_match_ordinal);

  // Add a frame. It contains 5 new matches.
  std::string url =
      embedded_test_server()->GetURL("/find_in_simple_page.html").spec();
  std::string script = std::string() +
      "var frame = document.createElement('iframe');" +
      "frame.src = '" + url + "';" +
      "document.body.appendChild(frame);";
  delegate()->MarkNextReply();
  ASSERT_TRUE(ExecJs(shell(), script));
  delegate()->WaitForNextReply();

  // The matches from the new frame should be found automatically, and the first
  // match in the frame should be activated.
  results = delegate()->GetFindResults();
  EXPECT_EQ(5, results.number_of_matches);
  EXPECT_EQ(1, results.active_match_ordinal);
}

// Tests a frame navigating to a different page during a find session.
IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, MAYBE(NavigateFrame)) {
  LoadMultiFramePage(2 /* height */, test_with_oopif() /* cross_process */);

  auto options = blink::mojom::FindOptions::New();
  options->run_synchronously_for_testing = true;
  Find("result", options.Clone());
  options->new_session = false;
  options->forward = false;
  Find("result", options.Clone());
  Find("result", options.Clone());
  Find("result", options.Clone());
  delegate()->WaitForFinalReply();

  FindResults results = delegate()->GetFindResults();
  EXPECT_EQ(last_request_id(), results.request_id);
  EXPECT_EQ(21, results.number_of_matches);
  EXPECT_EQ(19, results.active_match_ordinal);

  // Navigate one of the empty frames to a page with 5 matches.
  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
                            ->GetPrimaryFrameTree()
                            .root();
  GURL url(embedded_test_server()->GetURL(test_with_oopif() ? "b.com" : "a.com",
                                          "/find_in_simple_page.html"));
  delegate()->MarkNextReply();
  TestNavigationObserver navigation_observer(contents());
  EXPECT_TRUE(NavigateToURLFromRenderer(
      root->child_at(0)->child_at(1)->child_at(0), url));
  EXPECT_TRUE(navigation_observer.last_navigation_succeeded());
  delegate()->WaitForNextReply();

  // The navigation results in an extra reply before the one we care about. This
  // extra reply happens because the RenderFrameHost changes before it navigates
  // (because the navigation is cross-origin). The first reply will not change
  // the number of matches because the frame that is navigating was empty
  // before.
  if (delegate()->GetFindResults().number_of_matches == 21) {
    delegate()->MarkNextReply();
    delegate()->WaitForNextReply();
  }

  // The number of matches and the active match ordinal should update
  // automatically to include the new matches.
  results = delegate()->GetFindResults();
  EXPECT_EQ(26, results.number_of_matches);
  EXPECT_EQ(24, results.active_match_ordinal);
}

// Tests Searching in a hidden frame. Matches in the hidden frame should be
// ignored.
IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, MAYBE(HiddenFrame)) {
  LoadAndWait("/find_in_hidden_frame.html");

  auto default_options = blink::mojom::FindOptions::New();
  default_options->run_synchronously_for_testing = true;
  Find("hello", default_options.Clone());
  delegate()->WaitForFinalReply();
  FindResults results = delegate()->GetFindResults();

  EXPECT_EQ(last_request_id(), results.request_id);
  EXPECT_EQ(1, results.number_of_matches);
  EXPECT_EQ(1, results.active_match_ordinal);
}

// Tests that new matches can be found in dynamically added text.
// TODO(crbug.com/330194342): Deflake and re-enable.
#if BUILDFLAG(IS_ANDROID) || \
    (BUILDFLAG(IS_LINUX) && !defined(UNDEFINED_SANITIZER))
#define MAYBE_FindNewMatches DISABLED_FindNewMatches
#else
#define MAYBE_FindNewMatches FindNewMatches
#endif
IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, MAYBE_FindNewMatches) {
  LoadAndWait("/find_in_dynamic_page.html");

  auto options = blink::mojom::FindOptions::New();
  options->run_synchronously_for_testing = true;
  Find("result", options.Clone());
  options->new_session = false;
  Find("result", options.Clone());
  Find("result", options.Clone());
  delegate()->WaitForFinalReply();

  FindResults results = delegate()->GetFindResults();
  EXPECT_EQ(last_request_id(), results.request_id);
  EXPECT_EQ(3, results.number_of_matches);
  EXPECT_EQ(3, results.active_match_ordinal);

  // Dynamically add new text to the page. This text contains 5 new matches for
  // "result".
  ASSERT_TRUE(ExecJs(contents()->GetPrimaryMainFrame(), "addNewText()"));

  Find("result", options.Clone());
  delegate()->WaitForFinalReply();

  results = delegate()->GetFindResults();
  EXPECT_EQ(last_request_id(), results.request_id);
  EXPECT_EQ(8, results.number_of_matches);
  EXPECT_EQ(4, results.active_match_ordinal);
}

// TODO(crbug.com/40470937): These tests frequently fail on Android.
// TODO(crbug.com/41352658): Flaky timeout on Win7 (dbg).
// TODO(crbug.com/41408666): Flaky on Win10.
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN)
#define MAYBE_FindInPage_Issue627799 DISABLED_FindInPage_Issue627799
#else
#define MAYBE_FindInPage_Issue627799 FindInPage_Issue627799
#endif

IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, MAYBE_FindInPage_Issue627799) {
  LoadAndWait("/find_in_long_page.html");

  auto options = blink::mojom::FindOptions::New();
  options->run_synchronously_for_testing = true;
  Find("42", options.Clone());
  delegate()->WaitForFinalReply();

  FindResults results = delegate()->GetFindResults();
  EXPECT_EQ(last_request_id(), results.request_id);
  EXPECT_EQ(970, results.number_of_matches);
  EXPECT_EQ(1, results.active_match_ordinal);

  delegate()->StartReplyRecord();
  options->new_session = false;
  options->forward = false;
  Find("42", options.Clone());
  delegate()->WaitForFinalReply();

  // This is the crux of the issue that this test guards against. Searching
  // across the frame boundary should not cause the frame to be re-scoped. If
  // the re-scope occurs, then we will see the number of matches change in one
  // of the recorded find replies.
  for (auto& reply : delegate()->GetReplyRecord()) {
    EXPECT_EQ(last_request_id(), reply.request_id);
    EXPECT_TRUE(reply.number_of_matches == kInvalidId ||
                reply.number_of_matches == results.number_of_matches);
  }
}

IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, DetachFrameWithMatch) {
  // Detaching an iframe with matches when the main document doesn't
  // have matches should work and just remove the matches from the
  // removed frame.
  LoadAndWait("/find_in_page_two_frames.html");
  auto options = blink::mojom::FindOptions::New();
  options->run_synchronously_for_testing = true;

  Find("result", options.Clone());
  delegate()->WaitForFinalReply();
  FindResults results = delegate()->GetFindResults();
  EXPECT_EQ(last_request_id(), results.request_id);
  EXPECT_EQ(6, results.number_of_matches);
  EXPECT_EQ(1, results.active_match_ordinal);
  EXPECT_TRUE(ExecJs(shell(),
                     "document.body.removeChild("
                     "document.querySelectorAll('iframe')[0])"));

  Find("result", options.Clone());
  delegate()->WaitForFinalReply();
  results = delegate()->GetFindResults();
  EXPECT_EQ(last_request_id(), results.request_id);
  EXPECT_EQ(3, results.number_of_matches);
  EXPECT_EQ(1, results.active_match_ordinal);
}

IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, MAYBE(FindInPage_Issue644448)) {
  TestNavigationObserver navigation_observer(contents());
  EXPECT_TRUE(NavigateToURL(shell(), GURL("about:blank")));
  EXPECT_TRUE(navigation_observer.last_navigation_succeeded());

  auto default_options = blink::mojom::FindOptions::New();
  default_options->run_synchronously_for_testing = true;
  Find("result", default_options.Clone());
  delegate()->WaitForFinalReply();

  // Initially, there are no matches on the page.
  FindResults results = delegate()->GetFindResults();
  EXPECT_EQ(last_request_id(), results.request_id);
  EXPECT_EQ(0, results.number_of_matches);
  EXPECT_EQ(0, results.active_match_ordinal);

  // Load a page with matches.
  LoadAndWait("/find_in_simple_page.html");

  Find("result", default_options.Clone());
  delegate()->WaitForFinalReply();

  // There should now be matches found. When the bug was present, there were
  // still no matches found.
  results = delegate()->GetFindResults();
  EXPECT_EQ(last_request_id(), results.request_id);
  EXPECT_EQ(5, results.number_of_matches);
}

#if BUILDFLAG(IS_ANDROID)
// Tests empty active match rect when kWrapAround is false.
IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, EmptyActiveMatchRect) {
  LoadAndWait("/find_in_page.html");

  // kWrapAround is false by default.
  auto default_options = blink::mojom::FindOptions::New();
  default_options->run_synchronously_for_testing = true;
  Find("result 01", default_options.Clone());
  delegate()->WaitForFinalReply();
  EXPECT_EQ(1, delegate()->GetFindResults().number_of_matches);

  // Request the find match rects.
  contents()->RequestFindMatchRects(-1);
  delegate()->WaitForMatchRects();
  const std::vector<gfx::RectF>& rects = delegate()->find_match_rects();

  // The first match should be active.
  EXPECT_EQ(rects[0], delegate()->active_match_rect());

  Find("result 00", default_options.Clone());
  delegate()->WaitForFinalReply();
  EXPECT_EQ(1, delegate()->GetFindResults().number_of_matches);

  // Request the find match rects.
  contents()->RequestFindMatchRects(-1);
  delegate()->WaitForMatchRects();

  // The active match rect should be empty.
  EXPECT_EQ(gfx::RectF(), delegate()->active_match_rect());
}

class MainFrameSizeChangedWaiter : public WebContentsObserver {
 public:
  MainFrameSizeChangedWaiter(WebContents* web_contents)
      : WebContentsObserver(web_contents) {}
  void Wait() { run_loop_.Run(); }

 private:
  void FrameSizeChanged(RenderFrameHost* render_frame_host,
                        const gfx::Size& frame_size) override {
    if (render_frame_host->IsInPrimaryMainFrame())
      run_loop_.Quit();
  }

  base::RunLoop run_loop_;
};

// Tests match rects in the iframe are updated with the size of the main frame,
// and the active match rect should be in it.
IN_PROC_BROWSER_TEST_F(FindRequestManagerTest,
                       RectsUpdateWhenMainFrameSizeChanged) {
  LoadAndWait("/find_in_page.html");

  // Make a initial size for native view.
  const int kWidth = 1080;
  const int kHeight = 1286;
  gfx::Size size(kWidth, kHeight);
  contents()->GetNativeView()->OnSizeChanged(kWidth, kHeight);
  contents()->GetNativeView()->OnPhysicalBackingSizeChanged(size);

  // Make a FindRequest for "result".
  auto options = blink::mojom::FindOptions::New();
  options->run_synchronously_for_testing = true;
  Find("result", options->Clone());
  delegate()->WaitForFinalReply();
  EXPECT_EQ(19, delegate()->GetFindResults().number_of_matches);

  contents()->RequestFindMatchRects(-1);
  delegate()->WaitForMatchRects();

  // Change the size of native view.
  const int kNewHeight = 2121;
  size = gfx::Size(kWidth, kNewHeight);
  contents()->GetNativeView()->OnSizeChanged(kWidth, kNewHeight);
  contents()->GetNativeView()->OnPhysicalBackingSizeChanged(size);

  // Wait for the size of the mainframe to change, and then the position
  // of match rects should change as expected.
  MainFrameSizeChangedWaiter(contents()).Wait();

  contents()->RequestFindMatchRects(-1);
  delegate()->WaitForMatchRects();
  std::vector<gfx::RectF> new_rects = delegate()->find_match_rects();

  // The first match should be active.
  EXPECT_EQ(new_rects[0], delegate()->active_match_rect());

  // Check that all active rects (including iframe) matches with corresponding
  // match rect.
  for (int i = 1; i < 19; i++) {
    options->new_session = false;
    options->forward = true;
    Find("result", options->Clone());
    delegate()->WaitForFinalReply();

    EXPECT_EQ(19, delegate()->GetFindResults().number_of_matches);

    // Request the find match rects.
    contents()->RequestFindMatchRects(-1);
    delegate()->WaitForMatchRects();
    new_rects = delegate()->find_match_rects();

    // The active rect should be equal to the corresponding match rect.
    EXPECT_EQ(new_rects[i], delegate()->active_match_rect());
  }
}

// TODO(wjmaclean): This test, if re-enabled, may require work to make it
// OOPIF-compatible.
// Tests requesting find match rects.
IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, MAYBE(FindMatchRects)) {
  LoadAndWait("/find_in_page.html");
  if (test_with_oopif())
    MakeChildFrameCrossProcess();

  auto default_options = blink::mojom::FindOptions::New();
  default_options->run_synchronously_for_testing = true;
  Find("result", default_options.Clone());
  delegate()->WaitForFinalReply();
  EXPECT_EQ(19, delegate()->GetFindResults().number_of_matches);

  // Request the find match rects.
  contents()->RequestFindMatchRects(-1);
  delegate()->WaitForMatchRects();
  const std::vector<gfx::RectF>& rects = delegate()->find_match_rects();

  // The first match should be active.
  EXPECT_EQ(rects[0], delegate()->active_match_rect());

  // All results after the first two should be between them in find-in-page
  // coordinates. This is because results 2 to 19 are inside an iframe located
  // between results 0 and 1. This applies to the fixed div too.
  EXPECT_LT(rects[0].y(), rects[1].y());
  for (int i = 2; i < 19; ++i) {
    EXPECT_LT(rects[0].y(), rects[i].y());
    EXPECT_GT(rects[1].y(), rects[i].y());
  }

  // Result 3 should be below results 2 and 4. This is caused by the CSS
  // transform in the containing div. If the transform doesn't work then result
  // 3 will be between results 2 and 4.
  EXPECT_GT(rects[3].y(), rects[2].y());
  EXPECT_GT(rects[3].y(), rects[4].y());

  // Results 6, 7, 8 and 9 should be one below the other in that same order. If
  // overflow:scroll is not properly handled then result 8 would be below result
  // 9 or result 7 above result 6 depending on the scroll.
  EXPECT_LT(rects[6].y(), rects[7].y());
  EXPECT_LT(rects[7].y(), rects[8].y());
  EXPECT_LT(rects[8].y(), rects[9].y());

  // Results 11, 12, 13 and 14 should be between results 10 and 15, as they are
  // inside the table.
  EXPECT_GT(rects[11].y(), rects[10].y());
  EXPECT_GT(rects[12].y(), rects[10].y());
  EXPECT_GT(rects[13].y(), rects[10].y());
  EXPECT_GT(rects[14].y(), rects[10].y());
  EXPECT_LT(rects[11].y(), rects[15].y());
  EXPECT_LT(rects[12].y(), rects[15].y());
  EXPECT_LT(rects[13].y(), rects[15].y());
  EXPECT_LT(rects[14].y(), rects[15].y());

  // Result 11 should be above results 12, 13 and 14 as it's in the table
  // header.
  EXPECT_LT(rects[11].y(), rects[12].y());
  EXPECT_LT(rects[11].y(), rects[13].y());
  EXPECT_LT(rects[11].y(), rects[14].y());

  // Result 11 should also be right of results 12, 13 and 14 because of the
  // colspan.
  EXPECT_GT(rects[11].x(), rects[12].x());
  EXPECT_GT(rects[11].x(), rects[13].x());
  EXPECT_GT(rects[11].x(), rects[14].x());

  // Result 12 should be left of results 11, 13 and 14 in the table layout.
  EXPECT_LT(rects[12].x(), rects[11].x());
  EXPECT_LT(rects[12].x(), rects[13].x());
  EXPECT_LT(rects[12].x(), rects[14].x());

  // Results 13, 12 and 14 should be one above the other in that order because
  // of the rowspan and vertical-align: middle by default.
  EXPECT_LT(rects[13].y(), rects[12].y());
  EXPECT_LT(rects[12].y(), rects[14].y());

  // Result 16 should be below result 15.
  EXPECT_GT(rects[15].y(), rects[14].y());

  // Result 18 should be normalized with respect to the position:relative div,
  // and not it's immediate containing div. Consequently, result 18 should be
  // above result 17.
  EXPECT_GT(rects[17].y(), rects[18].y());
}

namespace {

class ZoomToFindInPageRectMessageFilter
    : public blink::mojom::FrameWidgetHostInterceptorForTesting {
 public:
  ZoomToFindInPageRectMessageFilter(RenderWidgetHostImpl* rwhi)
      : impl_(rwhi->frame_widget_host_receiver_for_testing().SwapImplForTesting(
            this)),
        widget_message_seen_(false) {}

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

  ~ZoomToFindInPageRectMessageFilter() override {}

  blink::mojom::FrameWidgetHost* GetForwardingInterface() override {
    return impl_;
  }

  void Reset() {
    widget_rect_seen_ = gfx::Rect();
    widget_message_seen_ = false;
  }

  void WaitForWidgetHostMessage() {
    if (widget_message_seen_)
      return;

    base::RunLoop run_loop;
    quit_closure_ = run_loop.QuitClosure();
    run_loop.Run();
  }

  gfx::Rect& widget_message_rect() { return widget_rect_seen_; }

 private:
  void ZoomToFindInPageRectInMainFrame(const gfx::Rect& rect_to_zoom) override {
    widget_rect_seen_ = rect_to_zoom;
    widget_message_seen_ = true;
    if (!quit_closure_.is_null())
      std::move(quit_closure_).Run();
  }

  raw_ptr<blink::mojom::FrameWidgetHost> impl_;
  gfx::Rect widget_rect_seen_;
  bool widget_message_seen_;
  base::OnceClosure quit_closure_;
};

}  // namespace

// Tests activating the find match nearest to a given point.
// TODO(crbug.com/40864045): Fix flaky failures.
IN_PROC_BROWSER_TEST_P(FindRequestManagerTest,
                       DISABLED_ActivateNearestFindMatch) {
  LoadAndWait("/find_in_page.html");
  if (test_with_oopif())
    MakeChildFrameCrossProcess();

  std::unique_ptr<ZoomToFindInPageRectMessageFilter> message_interceptor_child;

  if (test_with_oopif()) {
    message_interceptor_child =
        std::make_unique<ZoomToFindInPageRectMessageFilter>(
            first_child()->current_frame_host()->GetRenderWidgetHost());
  }

  auto default_options = blink::mojom::FindOptions::New();
  default_options->run_synchronously_for_testing = true;
  Find("result", default_options.Clone());
  delegate()->WaitForFinalReply();
  EXPECT_EQ(19, delegate()->GetFindResults().number_of_matches);

  auto* find_request_manager = contents()->GetFindRequestManagerForTesting();

  // Get the find match rects.
  contents()->RequestFindMatchRects(-1);
  delegate()->WaitForMatchRects();
  const std::vector<gfx::RectF>& rects = delegate()->find_match_rects();

  double device_scale_factor = GetFrameDeviceScaleFactor(contents());

  // Activate matches via points inside each of the find match rects, in an
  // arbitrary order. Check that the correct match becomes active after each
  // activation.
  const std::array<int, 19> order = {11, 13, 2, 0,  16, 5, 7, 10, 6, 1,
                                     15, 14, 9, 17, 18, 3, 8, 12, 4};
  for (const int rect_index : order) {
    delegate()->MarkNextReply();
    contents()->ActivateNearestFindResult(rects[rect_index].CenterPoint().x(),
                                          rects[rect_index].CenterPoint().y());
    delegate()->WaitForNextReply();

    bool is_match_in_oopif = rect_index > 1 && test_with_oopif();
    // Check widget message rect to make sure it matches.
    if (is_match_in_oopif) {
      message_interceptor_child->WaitForWidgetHostMessage();
      auto expected_rect = gfx::ScaleToEnclosingRect(
          message_interceptor_child->widget_message_rect(),
          1.f / device_scale_factor);
      EXPECT_EQ(find_request_manager->GetSelectionRectForTesting(),
                expected_rect);
      message_interceptor_child->Reset();
    }

    EXPECT_EQ(rect_index + 1,
              delegate()->GetFindResults().active_match_ordinal);
  }
}
#endif  // BUILDFLAG(IS_ANDROID)

// Test basic find-in-page functionality after going back and forth to the same
// page. In particular, find-in-page should continue to work after going back to
// a page using the back-forward cache.
// Flaky everywhere: https://crbug.com/1115102
IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, DISABLED_HistoryBackAndForth) {
  GURL url_a = embedded_test_server()->GetURL("a.com", "/find_in_page.html");
  GURL url_b = embedded_test_server()->GetURL("b.com", "/find_in_page.html");

  auto test_page = [&] {
    if (test_with_oopif())
      MakeChildFrameCrossProcess();

    auto options = blink::mojom::FindOptions::New();

    // The initial find-in-page request.
    Find("result", options->Clone());
    delegate()->WaitForFinalReply();

    FindResults results = delegate()->GetFindResults();
    EXPECT_EQ(last_request_id(), results.request_id);
    EXPECT_EQ(19, results.number_of_matches);

    // Iterate forward/backward over a few elements.
    int match_index = results.active_match_ordinal;
    for (int delta : {-1, -1, +1, +1, +1, +1, -1, +1, +1}) {
      options->new_session = false;
      options->forward = delta > 0;
      // |active_match_ordinal| uses 1-based index. It belongs to [1, 19].
      match_index += delta;
      match_index = (match_index + 18) % 19 + 1;

      Find("result", options->Clone());
      delegate()->WaitForFinalReply();
      results = delegate()->GetFindResults();

      EXPECT_EQ(last_request_id(), results.request_id);
      EXPECT_EQ(19, results.number_of_matches);
      EXPECT_EQ(match_index, results.active_match_ordinal);
    }
  };

  // 1) Navigate to A.
  EXPECT_TRUE(NavigateToURL(shell(), url_a));
  test_page();

  // 2) Navigate to B.
  EXPECT_TRUE(NavigateToURL(shell(), url_b));
  test_page();

  // 3) Go back to A.
  contents()->GetController().GoBack();
  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
  test_page();

  // 4) Go forward to B.
  contents()->GetController().GoForward();
  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
  test_page();
}

class FindInPageDisabledForOriginBrowserClient
    : public ContentBrowserTestContentBrowserClient {
 public:
  // ContentBrowserClient:
  bool IsFindInPageDisabledForOrigin(const url::Origin& origin) override {
    return origin.host() == "b.com";
  }
};

// Tests that find-in-page won't show results for origins that disabled
// find-in-page.
IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, FindInPageDisabledForOrigin) {
  FindInPageDisabledForOriginBrowserClient browser_client;

  // Start with a basic case to set a baseline.
  LoadAndWait("/find_in_page.html");
  url::Origin root_origin = GetOriginForFrameTreeNode(root());
  url::Origin child_origin = GetOriginForFrameTreeNode(first_child());
  EXPECT_EQ("a.com", root_origin.host());
  EXPECT_EQ("a.com", child_origin.host());
  EXPECT_FALSE(browser_client.IsFindInPageDisabledForOrigin(root_origin));
  EXPECT_FALSE(browser_client.IsFindInPageDisabledForOrigin(child_origin));

  auto options = blink::mojom::FindOptions::New();
  options->run_synchronously_for_testing = true;
  Find("result", options->Clone());
  delegate()->WaitForFinalReply();

  FindResults results = delegate()->GetFindResults();
  EXPECT_EQ(last_request_id(), results.request_id);
  EXPECT_EQ(19, results.number_of_matches);

  // Navigate child frame to b.com.
  EXPECT_TRUE(NavigateToURLFromRenderer(
      first_child(), embedded_test_server()->GetURL(
                         "b.com", first_child()->current_url().GetPath())));
  root_origin = GetOriginForFrameTreeNode(root());
  child_origin = GetOriginForFrameTreeNode(first_child());
  EXPECT_EQ("a.com", root_origin.host());
  EXPECT_EQ("b.com", child_origin.host());
  EXPECT_FALSE(browser_client.IsFindInPageDisabledForOrigin(root_origin));
  EXPECT_TRUE(browser_client.IsFindInPageDisabledForOrigin(child_origin));

  Find("result", options->Clone());
  delegate()->WaitForFinalReply();

  // Given the custom `browser_client` disabled find-in-page for b.com, only the
  // results from the root node should show up now.
  results = delegate()->GetFindResults();
  EXPECT_EQ(last_request_id(), results.request_id);
  EXPECT_EQ(2, results.number_of_matches);

  // Navigate child frame, but remain on b.com.
  EXPECT_TRUE(NavigateToURLFromRenderer(
      first_child(),
      embedded_test_server()->GetURL("b.com", "/find_in_simple_page.html")));
  root_origin = GetOriginForFrameTreeNode(root());
  child_origin = GetOriginForFrameTreeNode(first_child());
  EXPECT_EQ("a.com", root_origin.host());
  EXPECT_EQ("b.com", child_origin.host());
  EXPECT_FALSE(browser_client.IsFindInPageDisabledForOrigin(root_origin));
  EXPECT_TRUE(browser_client.IsFindInPageDisabledForOrigin(child_origin));

  // Results from the child frame on b.com still do not show up.
  results = delegate()->GetFindResults();
  EXPECT_EQ(last_request_id(), results.request_id);
  EXPECT_EQ(2, results.number_of_matches);

  // Navigate child frame to a.com again.
  EXPECT_TRUE(NavigateToURLFromRenderer(
      first_child(),
      embedded_test_server()->GetURL("a.com", "/find_in_simple_page.html")));
  root_origin = GetOriginForFrameTreeNode(root());
  child_origin = GetOriginForFrameTreeNode(first_child());
  EXPECT_EQ("a.com", root_origin.host());
  EXPECT_EQ("a.com", child_origin.host());
  EXPECT_FALSE(browser_client.IsFindInPageDisabledForOrigin(root_origin));
  EXPECT_FALSE(browser_client.IsFindInPageDisabledForOrigin(child_origin));

  Find("result", options->Clone());
  delegate()->WaitForFinalReply();

  // Since the child frame is now on a.com, find-in-page is enabled, so its
  // results show up again.
  results = delegate()->GetFindResults();
  EXPECT_EQ(last_request_id(), results.request_id);
  EXPECT_EQ(7, results.number_of_matches);
}

class FindTestWebContentsPrerenderingDelegate
    : public FindTestWebContentsDelegate {
 public:
  PreloadingEligibility IsPrerender2Supported(
      WebContents& web_contents,
      PreloadingTriggerType trigger_type) override {
    return PreloadingEligibility::kEligible;
  }
};

class FindRequestManagerPrerenderingTest : public FindRequestManagerTest {
 public:
  FindRequestManagerPrerenderingTest()
      : prerender_helper_(base::BindRepeating(
            &FindRequestManagerPrerenderingTest::web_contents,
            base::Unretained(this))) {}
  ~FindRequestManagerPrerenderingTest() override = default;

  void SetUpOnMainThread() override {
    FindRequestManagerTest::SetUpOnMainThread();
    contents()->SetDelegate(&delegate_);
  }

  content::test::PrerenderTestHelper* prerender_helper() {
    return &prerender_helper_;
  }

  content::WebContents* web_contents() { return shell()->web_contents(); }

 private:
  content::test::PrerenderTestHelper prerender_helper_;
  FindTestWebContentsPrerenderingDelegate delegate_;
};

// Tests that find-in-page won't show results inside a prerendering page.
IN_PROC_BROWSER_TEST_F(FindRequestManagerPrerenderingTest, Basic) {
  EXPECT_TRUE(
      NavigateToURL(shell(), embedded_test_server()->GetURL("/empty.html")));
  auto options = blink::mojom::FindOptions::New();
  options->run_synchronously_for_testing = true;
  Find("result", options->Clone());
  delegate()->WaitForFinalReply();

  // Do a find-in-page on an empty page.
  FindResults results = delegate()->GetFindResults();
  EXPECT_EQ(last_request_id(), results.request_id);
  EXPECT_EQ(0, results.number_of_matches);

  // Load a page that has 5 matches for "result" in the prerender.
  auto prerender_url =
      embedded_test_server()->GetURL("/find_in_simple_page.html?prerendering");
  prerender_helper()->AddPrerender(prerender_url);

  Find("result", options->Clone());
  delegate()->WaitForFinalReply();

  results = delegate()->GetFindResults();
  EXPECT_EQ(last_request_id(), results.request_id);
  // The prerendering page shouldn't affect the results of a find-in-page .
  EXPECT_EQ(0, results.number_of_matches);

  // Activate the page from the prerendering.
  prerender_helper()->NavigatePrimaryPage(prerender_url);
  Find("result", options->Clone());
  delegate()->WaitForFinalReply();

  results = delegate()->GetFindResults();
  // The results from the prerendered page getting activated should be 5 as the
  // mainframe(5 results) and no subframe.
  EXPECT_EQ(5, results.number_of_matches);
}

class FindRequestManagerTestWithBFCache : public FindRequestManagerTest {
 public:
  FindRequestManagerTestWithBFCache() {
    scoped_feature_list_.InitWithFeaturesAndParameters(
        GetDefaultEnabledBackForwardCacheFeaturesForTesting(
            /*ignore_outstanding_network_request=*/false),
        GetDefaultDisabledBackForwardCacheFeaturesForTesting());
  }
  ~FindRequestManagerTestWithBFCache() override = default;

  content::RenderFrameHost* render_frame_host() {
    return contents()->GetPrimaryMainFrame();
  }

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

// Test basic find-in-page functionality when a page gets into and out of
// BFCache.
IN_PROC_BROWSER_TEST_F(FindRequestManagerTestWithBFCache, Basic) {
  GURL url_a = embedded_test_server()->GetURL("a.com", "/find_in_page.html");
  GURL url_b =
      embedded_test_server()->GetURL("b.com", "/find_in_simple_page.html");

  auto options = blink::mojom::FindOptions::New();
  auto expect_match_results = [&](int expected_number_of_matches) {
    // The initial find-in-page request.
    Find("result", options->Clone());
    delegate()->WaitForFinalReply();

    FindResults results = delegate()->GetFindResults();
    EXPECT_EQ(last_request_id(), results.request_id);
    EXPECT_EQ(expected_number_of_matches, results.number_of_matches);
  };

  // 1) Navigate to A.
  EXPECT_TRUE(NavigateToURL(shell(), url_a));
  content::RenderFrameHostWrapper rfh_a(render_frame_host());
  // The results from the page A should be 19 as the mainframe(2 results) and
  // the new subframe (17 results).
  expect_match_results(19);

  // 2) Navigate to B.
  EXPECT_TRUE(NavigateToURL(shell(), url_b));
  content::RenderFrameHostWrapper rfh_b(render_frame_host());
  // The results from the page B should be 5 as the mainframe(5 results) and no
  // subframe.
  expect_match_results(5);

  // Ensure A is cached.
  EXPECT_EQ(rfh_a->GetLifecycleState(),
            content::RenderFrameHost::LifecycleState::kInBackForwardCache);

  // 3) Go back to A.
  contents()->GetController().GoBack();
  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
  // |rfh_a| should become the active frame.
  EXPECT_TRUE(rfh_a->IsInPrimaryMainFrame());
  // The results from the page A should be 19 as the mainframe(2 results) and
  // the new subframe (17 results).
  expect_match_results(19);

  // Ensure B is cached.
  EXPECT_EQ(rfh_b->GetLifecycleState(),
            content::RenderFrameHost::LifecycleState::kInBackForwardCache);

  // 4) Go forward to B.
  contents()->GetController().GoForward();
  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
  // |rfh_b| should become the active frame.
  EXPECT_TRUE(rfh_b->IsInPrimaryMainFrame());
  // The results from the page B should be 5 as the mainframe(5 results) and no
  // subframe.
  expect_match_results(5);
}

class WaitForFindTestWebContentsDelegate : public FindTestWebContentsDelegate {
 public:
  void WaitForFramesReply(int wait_count) {
    wait_count_ = wait_count;
    EXPECT_GT(wait_count_, 0);
    run_loop_ = std::make_unique<base::RunLoop>();
    run_loop_->Run();
    run_loop_.reset();
  }

  void TryToStopWaiting() {
    if (run_loop_ && !--wait_count_)
      run_loop_->Quit();
  }

  bool ShouldWait() { return wait_count_ > 0; }

 private:
  int wait_count_ = 0;
  std::unique_ptr<base::RunLoop> run_loop_;
};

class FindRequestManagerFencedFrameTest : public FindRequestManagerTest {
 public:
  FindRequestManagerFencedFrameTest() = default;
  ~FindRequestManagerFencedFrameTest() override = default;
  FindRequestManagerFencedFrameTest(const FindRequestManagerFencedFrameTest&) =
      delete;

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

  content::test::FencedFrameTestHelper& fenced_frame_test_helper() {
    return fenced_frame_helper_;
  }

  content::WebContents* GetWebContents() { return shell()->web_contents(); }

  int find_request_queue_size() {
    return contents()
        ->GetFindRequestManagerForTesting()
        ->find_request_queue_.size();
  }

  bool CheckFrame(RenderFrameHost* render_frame_host) const {
    return contents()->GetFindRequestManagerForTesting()->CheckFrame(
        render_frame_host);
  }

 private:
  content::test::FencedFrameTestHelper fenced_frame_helper_;
};

// This find-in-page client will make the find-request-queue not empty so that
// we can test a fenced frame doesn't clear the find-request-queue when it's
// deleted. To keep the find-request-queue not empty, this class
// intercepts the Mojo methods calls, and changes the FindMatchUpdateType to
// kMoreUpdatesComing (including those that were marked as kFinalUpdate), so
// that the find-request-queue won't get popped and will stay non-empty.
class NeverFinishFencedFrameFindInPageClient : public FindInPageClient {
 public:
  NeverFinishFencedFrameFindInPageClient(
      FindRequestManager* find_request_manager,
      RenderFrameHostImpl* rfh)
      : FindInPageClient(find_request_manager, rfh) {
    content::WebContents* web_contents =
        content::WebContents::FromRenderFrameHost(rfh);
    delegate_ = static_cast<WaitForFindTestWebContentsDelegate*>(
        web_contents->GetDelegate());
  }
  ~NeverFinishFencedFrameFindInPageClient() override = default;

  // blink::mojom::FindInPageClient overrides
  void SetNumberOfMatches(
      int request_id,
      unsigned int current_number_of_matches,
      blink::mojom::FindMatchUpdateType update_type) override {
    update_type = blink::mojom::FindMatchUpdateType::kMoreUpdatesComing;
    FindInPageClient::SetNumberOfMatches(request_id, current_number_of_matches,
                                         update_type);
  }

  // Do nothing on SetActiveMatch() calls, since this can potentially trigger
  // FindRequestManager::AdvanceQueue() and pop an item from the
  // find-request-queue.
  void SetActiveMatch(int request_id,
                      const gfx::Rect& active_match_rect,
                      int active_match_ordinal,
                      blink::mojom::FindMatchUpdateType update_type) override {}

 private:
  raw_ptr<WaitForFindTestWebContentsDelegate> delegate_;
};

static std::unique_ptr<FindInPageClient> CreateFencedFrameFindInPageClient(
    FindRequestManager* find_request_manager,
    RenderFrameHostImpl* rfh) {
  return std::make_unique<NeverFinishFencedFrameFindInPageClient>(
      find_request_manager, rfh);
}

// Tests that a main frame, a sub frame, and a fenced frame clear the
// find-request-queue when the fenced frame is deleted.
IN_PROC_BROWSER_TEST_F(FindRequestManagerFencedFrameTest,
                       OnlyPrimaryMainFrameClearsFindRequestQueue) {
  WaitForFindTestWebContentsDelegate delegate;
  contents()->SetDelegate(&delegate);

  // Override the FindInPageClient class so that we can intercept the Mojo
  // methods calls to keep its find request queue non-empty.
  contents()
      ->GetFindRequestManagerForTesting()
      ->SetCreateFindInPageClientFunctionForTesting(
          &CreateFencedFrameFindInPageClient);

  LoadAndWait("/find_in_page.html");
  auto options = blink::mojom::FindOptions::New();
  options->run_synchronously_for_testing = true;
  Find("result", options.Clone());
  // Initial find request is pop from the queue immediately so we make a second
  // find request.
  options->new_session = false;
  Find("result", options.Clone());

  // Create a fenced frame.
  GURL find_test_url =
      embedded_test_server()->GetURL("/fenced_frames/find_in_page.html");
  content::RenderFrameHost* fenced_frame_host =
      fenced_frame_test_helper().CreateFencedFrame(
          GetWebContents()->GetPrimaryMainFrame(), find_test_url);
  EXPECT_NE(nullptr, fenced_frame_host);
  EXPECT_TRUE(CheckFrame(fenced_frame_host));
  EXPECT_EQ(find_request_queue_size(), 1);
  EXPECT_EQ(last_request_id(), delegate.GetFindResults().request_id);

  // Navigate the fenced frame, this won't cause the find request queue to be
  // cleared, since it's not a primary main frame.
  fenced_frame_host = fenced_frame_test_helper().NavigateFrameInFencedFrameTree(
      fenced_frame_host, find_test_url);
  EXPECT_TRUE(CheckFrame(fenced_frame_host));
  EXPECT_EQ(find_request_queue_size(), 1);
  EXPECT_EQ(last_request_id(), delegate.GetFindResults().request_id);

  // Navigate the non-fenced frame subframe, this also won't cause the find
  // request queue to be cleared, since it's not a primary main frame.
  FrameTreeNode* root = contents()->GetPrimaryFrameTree().root();
  EXPECT_TRUE(NavigateToURLFromRenderer(root->child_at(0), find_test_url));
  EXPECT_TRUE(CheckFrame(root->child_at(0)->current_frame_host()));
  EXPECT_EQ(find_request_queue_size(), 1);
  EXPECT_EQ(last_request_id(), delegate.GetFindResults().request_id);

  // Navigate the main frame, this causes the find request queue to be cleared,
  // since it's the primary main frame.
  EXPECT_TRUE(NavigateToURL(shell(), find_test_url));
  EXPECT_TRUE(CheckFrame(GetWebContents()->GetPrimaryMainFrame()));
  EXPECT_EQ(find_request_queue_size(), 0);
}

// This find-in-page client will make it so that we never stop listening for
// find-in-page updates only for subframes, through modifying final updates to
// be marked as non-final updates. It helps us to simulate various things that
// can happen before a find-in-page session finishes (e.g. navigation,
// lifecycle state change) without finishing the find session.
class NeverFinishSubframeFindInPageClient : public FindInPageClient {
 public:
  NeverFinishSubframeFindInPageClient(FindRequestManager* find_request_manager,
                                      RenderFrameHostImpl* rfh)
      : FindInPageClient(find_request_manager, rfh), rfh_(rfh) {
    content::WebContents* web_contents =
        content::WebContents::FromRenderFrameHost(rfh);
    delegate_ = static_cast<WaitForFindTestWebContentsDelegate*>(
        web_contents->GetDelegate());
  }
  ~NeverFinishSubframeFindInPageClient() override = default;

  // blink::mojom::FindInPageClient overrides
  void SetNumberOfMatches(
      int request_id,
      unsigned int current_number_of_matches,
      blink::mojom::FindMatchUpdateType update_type) override {
    bool should_wait = delegate_->ShouldWait();
    if (update_type == blink::mojom::FindMatchUpdateType::kFinalUpdate)
      delegate_->TryToStopWaiting();

    // Make sure subframe's reply is not marked as the final update.
    if (!rfh_->is_main_frame() && should_wait)
      update_type = blink::mojom::FindMatchUpdateType::kMoreUpdatesComing;

    FindInPageClient::SetNumberOfMatches(request_id, current_number_of_matches,
                                         update_type);
  }

  void SetActiveMatch(int request_id,
                      const gfx::Rect& active_match_rect,
                      int active_match_ordinal,
                      blink::mojom::FindMatchUpdateType update_type) override {
    if (update_type == blink::mojom::FindMatchUpdateType::kFinalUpdate)
      delegate_->TryToStopWaiting();

    // Make sure subframe's reply is not marked as the final update.
    if (!rfh_->is_main_frame())
      update_type = blink::mojom::FindMatchUpdateType::kMoreUpdatesComing;

    FindInPageClient::SetActiveMatch(request_id, active_match_rect,
                                     active_match_ordinal, update_type);
  }

 private:
  raw_ptr<RenderFrameHostImpl> rfh_;
  raw_ptr<WaitForFindTestWebContentsDelegate> delegate_;
};

class FindRequestManagerTestObserver : public WebContentsObserver {
 public:
  explicit FindRequestManagerTestObserver(WebContents* web_contents)
      : WebContentsObserver(web_contents) {}

  void DidFinishLoad(RenderFrameHost* render_frame_host,
                     const GURL& url) override {
    auto* delegate = static_cast<FindTestWebContentsDelegate*>(
        web_contents()->GetDelegate());
    delegate->MarkNextReply();
  }
};

static std::unique_ptr<FindInPageClient> CreateFindInPageClient(
    FindRequestManager* find_request_manager,
    RenderFrameHostImpl* rfh) {
  return std::make_unique<NeverFinishSubframeFindInPageClient>(
      find_request_manager, rfh);
}

enum class FrameSiteType {
  kSameOrigin,
  kCrossOrigin,
};

enum class FrameTestType {
  kIFrame,
  kFencedFrame,
};

class FindRequestManagerTestWithTestConfig
    : public FindRequestManagerTestBase,
      public testing::WithParamInterface<
          ::testing::tuple<FrameSiteType, FrameTestType>> {
 public:
  FrameSiteType GetFrameSiteType() const { return std::get<0>(GetParam()); }

  FrameTestType GetFrameTestType() const { return std::get<1>(GetParam()); }

  test::FencedFrameTestHelper& fenced_frame_test_helper() {
    return fenced_frame_test_helper_;
  }

 private:
  test::FencedFrameTestHelper fenced_frame_test_helper_;
};

INSTANTIATE_TEST_SUITE_P(
    FindRequestManagers,
    FindRequestManagerTestWithTestConfig,
    ::testing::Combine(::testing::Values(FrameSiteType::kSameOrigin,
                                         FrameSiteType::kCrossOrigin),
                       ::testing::Values(FrameTestType::kIFrame,
                                         FrameTestType::kFencedFrame)));

// Tests that the previous results from old document are removed and we get the
// new results from the new document when we navigate the subframe that
// hasn't finished the find-in-page session to the new document.
// TODO(crbug.com/40220234): Fix flakiness and reenable the test.
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || \
    BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
#define MAYBE_NavigateFrameDuringFind DISABLED_NavigateFrameDuringFind
#else
#define MAYBE_NavigateFrameDuringFind NavigateFrameDuringFind
#endif
IN_PROC_BROWSER_TEST_P(FindRequestManagerTestWithTestConfig,
                       MAYBE_NavigateFrameDuringFind) {
  WaitForFindTestWebContentsDelegate delegate;
  contents()->SetDelegate(&delegate);

  // 1) Load a main frame with 5 matches.
  LoadAndWait("/find_in_simple_page.html");

  GURL frame_url =
      embedded_test_server()->GetURL("a.com", "/find_in_page_frame.html");
  content::RenderFrameHost* fenced_frame_host = nullptr;

  // 2) Load a subframe with 17 matches.
  if (GetFrameTestType() == FrameTestType::kIFrame) {
    EXPECT_TRUE(ExecJs(shell(), JsReplace(R"(
        var frame = document.createElement('iframe');
        frame.src = $1;
        document.body.appendChild(frame);
      )",
                                          frame_url)));
    ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
  } else {
    fenced_frame_host = fenced_frame_test_helper().CreateFencedFrame(
        shell()->web_contents()->GetPrimaryMainFrame(), frame_url);
    EXPECT_NE(nullptr, fenced_frame_host);
  }

  auto options = blink::mojom::FindOptions::New();
  options->run_synchronously_for_testing = true;

  // 2) First try a normal find-in-page session that finishes completely.
  Find("result", options.Clone());
  delegate.WaitForFinalReply();

  FindResults results = delegate.GetFindResults();
  EXPECT_EQ(last_request_id(), results.request_id);
  EXPECT_EQ(22, results.number_of_matches);
  EXPECT_EQ(1, results.active_match_ordinal);

  // 3) Override the FindInPageClient class so that we can simulate a subframe
  // change that happens in the middle of a find-in-page session.
  contents()
      ->GetFindRequestManagerForTesting()
      ->SetCreateFindInPageClientFunctionForTesting(&CreateFindInPageClient);

  // 4) Try to find-in-page again, but this time the subframe won't be marked as
  // finished before it got navigated.
  Find("result", options.Clone());

  // 5) Wait for the find request of the main frame's reply.
  delegate.WaitForFramesReply(2);
  results = delegate.GetFindResults();
  EXPECT_EQ(last_request_id(), results.request_id);
  EXPECT_EQ(22, results.number_of_matches);
  EXPECT_EQ(2, results.active_match_ordinal);

  // 6) Navigate the subframe that hasn't finished the find-in-page session to a
  // document with 5 matches. This will trigger a find-in-page request on the
  // new document on the unfinished subframe, and removes the result from the
  // old document.
  FindRequestManagerTestObserver observer(contents());
  GURL url(embedded_test_server()->GetURL(
      GetFrameSiteType() == FrameSiteType::kSameOrigin ? "a.com" : "b.com",
      "/find_in_simple_page.html"));
  if (GetFrameTestType() == FrameTestType::kIFrame) {
    FrameTreeNode* root = contents()->GetPrimaryFrameTree().root();
    TestNavigationObserver navigation_observer(contents());
    EXPECT_TRUE(NavigateToURLFromRenderer(root->child_at(0), url));
    EXPECT_TRUE(navigation_observer.last_navigation_succeeded());
  } else {
    fenced_frame_test_helper().NavigateFrameInFencedFrameTree(fenced_frame_host,
                                                              url);
  }

  delegate.WaitForNextReply();

  results = delegate.GetFindResults();
  EXPECT_EQ(last_request_id(), results.request_id);
  // The results from the old subframe (17 results) is removed entirely even
  // when it hasn't finished, and we added the next reply from the new subframe
  // (5 results). So, the final results should be 10 as the mainframe(5 results)
  // and the new subframe (5 results).
  EXPECT_EQ(10, results.number_of_matches);
  EXPECT_EQ(2, results.active_match_ordinal);
}

// Tests that the previous results from the old documents are removed and we
// get the new results from the new document when we go back to the page in
// BFCache from the page that hasn't finished the find-in-page session.
// This TC does not intentionally check the |active_match_ordinal| value,
// because the main frame is not focused on Android, so it has a different
// result on Android.
IN_PROC_BROWSER_TEST_F(FindRequestManagerTestWithBFCache,
                       NavigateFrameDuringFind) {
  WaitForFindTestWebContentsDelegate delegate;
  contents()->SetDelegate(&delegate);

  GURL url_a = embedded_test_server()->GetURL("a.com", "/find_in_page.html");
  GURL url_b =
      embedded_test_server()->GetURL("b.com", "/find_in_page_two_frames.html");

  // 1) Load A that is a main frame with 2 matches and a subframe with 17
  // matches.
  EXPECT_TRUE(NavigateToURL(shell(), url_a));
  content::RenderFrameHostWrapper rfh_a(render_frame_host());

  // 2) Load B that is a main frame with no match and two subframes with each 3
  // matches.
  EXPECT_TRUE(NavigateToURL(shell(), url_b));
  // Ensure A is cached.
  EXPECT_EQ(rfh_a->GetLifecycleState(),
            content::RenderFrameHost::LifecycleState::kInBackForwardCache);
  content::RenderFrameHostWrapper rfh_b(render_frame_host());

  // 3) Override the FindInPageClient class so that we can simulate a subframe
  // change that happens in the middle of a find-in-page session.
  contents()
      ->GetFindRequestManagerForTesting()
      ->SetCreateFindInPageClientFunctionForTesting(&CreateFindInPageClient);

  auto options = blink::mojom::FindOptions::New();
  options->run_synchronously_for_testing = true;

  // 4) Try to find-in-page again, but this time the subframe won't be marked as
  // finished before it goes back in the BF cache.
  Find("result", options.Clone());

  // 5) Wait for replies from the main frame and the subframes.
  delegate.WaitForFramesReply(3);
  FindResults results = delegate.GetFindResults();
  EXPECT_EQ(last_request_id(), results.request_id);
  EXPECT_EQ(6, results.number_of_matches);

  // 6) Go back to A which has a main frame with 2 matches and the subframe with
  // 17 matches.
  FindRequestManagerTestObserver observer1(contents());
  contents()->GetController().GoBack();
  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
  // |rfh_a| should become the active frame.
  EXPECT_TRUE(rfh_a->IsInPrimaryMainFrame());
  // Ensure B is cached.
  EXPECT_EQ(rfh_b->GetLifecycleState(),
            content::RenderFrameHost::LifecycleState::kInBackForwardCache);

  // 7) Wait for replies from the main frame and the subframes.
  delegate.WaitForFramesReply(2);
  results = delegate.GetFindResults();
  EXPECT_EQ(last_request_id(), results.request_id);
  // The results from the old page (6 results) is removed entirely even when
  // it hasn't finished, and we added the next reply from the new page (19
  // results). So, the final results should be 19.
  EXPECT_EQ(19, results.number_of_matches);

  // 8) Go forward to B which has a main frame with no match and two subframes
  // with each 3 matches.
  contents()->GetController().GoForward();
  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
  // |rfh_b| should become the active frame.
  EXPECT_TRUE(rfh_b->IsInPrimaryMainFrame());

  // 9) Wait for replies from the main frame and the subframes.
  delegate.WaitForFinalReply();
  results = delegate.GetFindResults();
  EXPECT_EQ(last_request_id(), results.request_id);
  // The results from the old page (19 results) is removed entirely even when
  // it hasn't finished, and we added the next reply from the new page (6
  // results). So, the final results should be 6.
  EXPECT_EQ(6, results.number_of_matches);
}

IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, CrashDuringFind) {
  WaitForFindTestWebContentsDelegate delegate;
  contents()->SetDelegate(&delegate);

  // 1) Load a main frame with 2 matches and a subframe with 17 matches.
  LoadAndWait("/find_in_page.html");
  MakeChildFrameCrossProcess();

  // 2) Override the FindInPageClient class so that we can simulate a subframe
  // change that happens in the middle of a find-in-page session.
  contents()
      ->GetFindRequestManagerForTesting()
      ->SetCreateFindInPageClientFunctionForTesting(&CreateFindInPageClient);

  auto options = blink::mojom::FindOptions::New();
  options->run_synchronously_for_testing = true;

  // 3) Try to find-in-page again, but this time the subframe won't be marked as
  // finished before it crashed.
  Find("result", options.Clone());

  // 4) Wait for the find request of the main frame's reply.
  delegate.WaitForFramesReply(2);
  FindResults results = delegate.GetFindResults();
  EXPECT_EQ(last_request_id(), results.request_id);
  EXPECT_EQ(19, results.number_of_matches);
  EXPECT_EQ(1, results.active_match_ordinal);

  // 5) Crash the subframe that hasn't finished the find-in-page
  // session. This will remove the result from the crashed document.
  {
    FrameTreeNode* root = contents()->GetPrimaryFrameTree().root();
    content::ScopedAllowRendererCrashes scoped_allow_renderer_crashes;
    content::RenderFrameDeletedObserver crash_observer(
        root->child_at(0)->current_frame_host());
    root->child_at(0)->current_frame_host()->GetProcess()->Shutdown(1);
    crash_observer.WaitUntilDeleted();
  }

  // 6) Wait for the crashed frame to be deleted.
  delegate.WaitForFinalReply();
  results = delegate.GetFindResults();
  EXPECT_EQ(last_request_id(), results.request_id);
  // The results from the crashed subframe (17 results) is removed entirely and
  // only have 2 results from the main frame.
  EXPECT_EQ(2, results.number_of_matches);
  EXPECT_EQ(1, results.active_match_ordinal);
}

IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, DelayThenStop) {
  LoadAndWait("/find_in_page.html");
  if (test_with_oopif())
    MakeChildFrameCrossProcess();

  auto default_options = blink::mojom::FindOptions::New();
  Find("r", default_options->Clone());
  contents()->StopFinding(STOP_FIND_ACTION_CLEAR_SELECTION);

  FindResults results = delegate()->GetFindResults();
  EXPECT_EQ(0, results.number_of_matches);

  EXPECT_FALSE(contents()
                   ->GetFindRequestManagerForTesting()
                   ->RunDelayedFindTaskForTesting());
}

}  // namespace content
