// Copyright 2012 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/public/test/browser_test_utils.h"

#include <stddef.h>

#include <algorithm>
#include <cstdint>
#include <set>
#include <string_view>
#include <tuple>
#include <utility>

#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/containers/span.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/functional/callback_forward.h"
#include "base/functional/callback_helpers.h"
#include "base/json/json_reader.h"
#include "base/memory/raw_ptr.h"
#include "base/no_destructor.h"
#include "base/process/kill.h"
#include "base/run_loop.h"
#include "base/scoped_observation.h"
#include "base/strings/pattern.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/bind.h"
#include "base/test/test_future.h"
#include "base/test/test_switches.h"
#include "base/test/test_timeouts.h"
#include "base/trace_event/typed_macros.h"
#include "base/types/optional_ref.h"
#include "base/types/optional_util.h"
#include "base/uuid.h"
#include "base/values.h"
#include "build/build_config.h"
#include "cc/test/pixel_test_utils.h"
#include "components/input/render_widget_host_input_event_router.h"
#include "components/viz/client/frame_evictor.h"
#include "components/viz/common/frame_sinks/copy_output_result.h"
#include "content/browser/file_system/file_system_manager_impl.h"
#include "content/browser/file_system_access/file_system_access_manager_impl.h"
#include "content/browser/renderer_host/cross_process_frame_connector.h"
#include "content/browser/renderer_host/frame_tree_node.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/navigation_request.h"
#include "content/browser/renderer_host/navigation_throttle_runner.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/render_frame_metadata_provider_impl.h"
#include "content/browser/renderer_host/render_frame_proxy_host.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_factory.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_child_frame.h"
#include "content/browser/screen_orientation/screen_orientation_provider.h"
#include "content/browser/storage_partition_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/browser/web_contents/web_contents_view.h"
#include "content/common/frame.mojom.h"
#include "content/common/input/synthetic_touchscreen_pinch_gesture.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_termination_info.h"
#include "content/public/browser/histogram_fetcher.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/navigation_throttle.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_observer.h"
#include "content/public/browser/screen_orientation_delegate.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/weak_document_ptr.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/isolated_world_ids.h"
#include "content/public/test/accessibility_notification_waiter.h"
#include "content/public/test/no_renderer_crashes_assertion.h"
#include "content/public/test/simple_url_loader_test_helper.h"
#include "content/public/test/synchronize_visual_properties_interceptor.h"
#include "content/public/test/test_devtools_protocol_client.h"
#include "content/public/test/test_fileapi_operation_waiter.h"
#include "content/public/test/test_frame_navigation_observer.h"
#include "content/public/test/test_launcher.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
#include "content/test/did_commit_navigation_interceptor.h"
#include "content/test/mock_commit_deferring_condition.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/completion_once_callback.h"
#include "net/base/filename_util.h"
#include "net/base/io_buffer.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_access_result.h"
#include "net/cookies/cookie_constants.h"
#include "net/cookies/cookie_util.h"
#include "net/filter/gzip_header.h"
#include "net/filter/gzip_source_stream.h"
#include "net/filter/mock_source_stream.h"
#include "net/filter/source_stream_type.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "net/test/python_utils.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/public/mojom/cookie_manager.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "services/network/public/mojom/network_service_test.mojom.h"
#include "storage/browser/blob/blob_url_registry.h"
#include "storage/browser/file_system/file_system_context.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/functional/overload.h"
#include "third_party/blink/public/common/chrome_debug_urls.h"
#include "third_party/blink/public/common/frame/frame_visual_properties.h"
#include "third_party/blink/public/common/input/synthetic_web_input_event_builders.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/blink/public/mojom/blob/blob_url_store.mojom-test-utils.h"
#include "third_party/blink/public/mojom/filesystem/file_system.mojom.h"
#include "third_party/blink/public/mojom/keyboard_lock/keyboard_lock.mojom-shared.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/accessibility/platform/browser_accessibility.h"
#include "ui/accessibility/platform/browser_accessibility_manager.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "ui/base/clipboard/test/test_clipboard.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/compositor/test/draw_waiter_for_test.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/gesture_detection/gesture_configuration.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/latency/latency_info.h"

#if !BUILDFLAG(IS_ANDROID)
#include "content/browser/media/captured_surface_controller.h"
#include "content/public/test/mock_captured_surface_controller.h"
#endif  // !BUILDFLAG(IS_ANDROID)

#if BUILDFLAG(IS_CHROMEOS)
#include "ash/webui/grit/ash_webui_common_resources.h"
#endif

#if BUILDFLAG(IS_WIN)
#include <combaseapi.h>
#include <wrl/client.h>

#include "base/win/scoped_safearray.h"
#include "base/win/scoped_variant.h"

#include <uiautomation.h>
#endif

#if defined(USE_AURA)
#include "content/browser/renderer_host/delegated_frame_host.h"
#include "content/browser/renderer_host/render_widget_host_view_aura.h"
#include "ui/aura/test/window_event_dispatcher_test_api.h"
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_tree_host.h"
#include "ui/events/event.h"
#endif  // USE_AURA

namespace content {
namespace {

void BuildSimpleWebKeyEvent(blink::WebInputEvent::Type type,
                            ui::DomKey key,
                            ui::DomCode code,
                            ui::KeyboardCode key_code,
                            input::NativeWebKeyboardEvent* event) {
  event->dom_key = key;
  event->dom_code = static_cast<int>(code);
  event->native_key_code = ui::KeycodeConverter::DomCodeToNativeKeycode(code);
  event->windows_key_code = key_code;
  event->is_system_key = false;
  event->skip_if_unhandled = true;

  if (type == blink::WebInputEvent::Type::kChar ||
      type == blink::WebInputEvent::Type::kRawKeyDown) {
    // |key| is the only parameter that contains information about the case of
    // the character. Use it to be able to generate lower case input.
    if (key.IsCharacter()) {
      event->text[0] = key.ToCharacter();
      event->unmodified_text[0] = key.ToCharacter();
    } else {
      event->text[0] = key_code;
      event->unmodified_text[0] = key_code;
    }
  }
}

void InjectRawKeyEvent(WebContents* web_contents,
                       blink::WebInputEvent::Type type,
                       ui::DomKey key,
                       ui::DomCode code,
                       ui::KeyboardCode key_code,
                       int modifiers) {
  input::NativeWebKeyboardEvent event(type, modifiers, base::TimeTicks::Now());
  BuildSimpleWebKeyEvent(type, key, code, key_code, &event);
  WebContentsImpl* web_contents_impl =
      static_cast<WebContentsImpl*>(web_contents);
  RenderWidgetHostImpl* main_frame_rwh =
      web_contents_impl->GetPrimaryMainFrame()->GetRenderWidgetHost();
  web_contents_impl->GetFocusedRenderWidgetHost(main_frame_rwh)
      ->ForwardKeyboardEvent(event);
}

int SimulateModifierKeysDown(WebContents* web_contents,
                             bool control,
                             bool shift,
                             bool alt,
                             bool command) {
  int modifiers = 0;

  // The order of these key down events shouldn't matter for our simulation.
  // For our simulation we can use either the left keys or the right keys.
  if (control) {
    modifiers |= blink::WebInputEvent::kControlKey;
    InjectRawKeyEvent(web_contents, blink::WebInputEvent::Type::kRawKeyDown,
                      ui::DomKey::CONTROL, ui::DomCode::CONTROL_LEFT,
                      ui::VKEY_CONTROL, modifiers);
  }
  if (shift) {
    modifiers |= blink::WebInputEvent::kShiftKey;
    InjectRawKeyEvent(web_contents, blink::WebInputEvent::Type::kRawKeyDown,
                      ui::DomKey::SHIFT, ui::DomCode::SHIFT_LEFT,
                      ui::VKEY_SHIFT, modifiers);
  }
  if (alt) {
    modifiers |= blink::WebInputEvent::kAltKey;
    InjectRawKeyEvent(web_contents, blink::WebInputEvent::Type::kRawKeyDown,
                      ui::DomKey::ALT, ui::DomCode::ALT_LEFT, ui::VKEY_MENU,
                      modifiers);
  }
  if (command) {
    modifiers |= blink::WebInputEvent::kMetaKey;
    InjectRawKeyEvent(web_contents, blink::WebInputEvent::Type::kRawKeyDown,
                      ui::DomKey::META, ui::DomCode::META_LEFT,
                      ui::VKEY_COMMAND, modifiers);
  }
  return modifiers;
}

int SimulateModifierKeysUp(WebContents* web_contents,
                           bool control,
                           bool shift,
                           bool alt,
                           bool command,
                           int modifiers) {
  // The order of these key releases shouldn't matter for our simulation.
  if (control) {
    modifiers &= ~blink::WebInputEvent::kControlKey;
    InjectRawKeyEvent(web_contents, blink::WebInputEvent::Type::kKeyUp,
                      ui::DomKey::CONTROL, ui::DomCode::CONTROL_LEFT,
                      ui::VKEY_CONTROL, modifiers);
  }

  if (shift) {
    modifiers &= ~blink::WebInputEvent::kShiftKey;
    InjectRawKeyEvent(web_contents, blink::WebInputEvent::Type::kKeyUp,
                      ui::DomKey::SHIFT, ui::DomCode::SHIFT_LEFT,
                      ui::VKEY_SHIFT, modifiers);
  }

  if (alt) {
    modifiers &= ~blink::WebInputEvent::kAltKey;
    InjectRawKeyEvent(web_contents, blink::WebInputEvent::Type::kKeyUp,
                      ui::DomKey::ALT, ui::DomCode::ALT_LEFT, ui::VKEY_MENU,
                      modifiers);
  }

  if (command) {
    modifiers &= ~blink::WebInputEvent::kMetaKey;
    InjectRawKeyEvent(web_contents, blink::WebInputEvent::Type::kKeyUp,
                      ui::DomKey::META, ui::DomCode::META_LEFT,
                      ui::VKEY_COMMAND, modifiers);
  }
  return modifiers;
}

void SimulateKeyEvent(WebContents* web_contents,
                      ui::DomKey key,
                      ui::DomCode code,
                      ui::KeyboardCode key_code,
                      bool send_char,
                      int modifiers) {
  InjectRawKeyEvent(web_contents, blink::WebInputEvent::Type::kRawKeyDown, key,
                    code, key_code, modifiers);
  if (send_char) {
    InjectRawKeyEvent(web_contents, blink::WebInputEvent::Type::kChar, key,
                      code, key_code, modifiers);
  }
  InjectRawKeyEvent(web_contents, blink::WebInputEvent::Type::kKeyUp, key, code,
                    key_code, modifiers);
}

void SimulateKeyPressImpl(WebContents* web_contents,
                          ui::DomKey key,
                          ui::DomCode code,
                          ui::KeyboardCode key_code,
                          bool control,
                          bool shift,
                          bool alt,
                          bool command,
                          bool send_char) {
  int modifiers =
      SimulateModifierKeysDown(web_contents, control, shift, alt, command);
  SimulateKeyEvent(web_contents, key, code, key_code, send_char, modifiers);
  modifiers = SimulateModifierKeysUp(web_contents, control, shift, alt, command,
                                     modifiers);
  ASSERT_EQ(modifiers, 0);
}

std::unique_ptr<net::test_server::HttpResponse>
CrossSiteRedirectResponseHandler(const net::EmbeddedTestServer* test_server,
                                 const net::test_server::HttpRequest& request) {
  net::HttpStatusCode http_status_code;

  // Inspect the prefix and extract the remainder of the url into |params|.
  size_t length_of_chosen_prefix;
  std::string prefix_302("/cross-site/");
  std::string prefix_307("/cross-site-307/");
  if (base::StartsWith(request.relative_url, prefix_302,
                       base::CompareCase::SENSITIVE)) {
    http_status_code = net::HTTP_MOVED_PERMANENTLY;
    length_of_chosen_prefix = prefix_302.length();
  } else if (base::StartsWith(request.relative_url, prefix_307,
                              base::CompareCase::SENSITIVE)) {
    http_status_code = net::HTTP_TEMPORARY_REDIRECT;
    length_of_chosen_prefix = prefix_307.length();
  } else {
    // Unrecognized prefix - let somebody else handle this request.
    return nullptr;
  }
  std::string params = request.relative_url.substr(length_of_chosen_prefix);

  // A hostname to redirect to must be included in the URL, therefore at least
  // one '/' character is expected.
  size_t slash = params.find('/');
  if (slash == std::string::npos) {
    return nullptr;
  }

  // Replace the host of the URL with the one passed in the URL.
  GURL::Replacements replace_host;
  replace_host.SetHostStr(std::string_view(params).substr(0, slash));
  GURL redirect_server =
      test_server->base_url().ReplaceComponents(replace_host);

  // Append the real part of the path to the new URL.
  std::string path = params.substr(slash + 1);
  GURL redirect_target(redirect_server.Resolve(path));
  DCHECK(redirect_target.is_valid());

  auto http_response = std::make_unique<net::test_server::BasicHttpResponse>();
  http_response->set_code(http_status_code);
  http_response->AddCustomHeader("Location", redirect_target.spec());
  return std::move(http_response);
}

// Helper class used by the TestNavigationManager to pause navigations.
// Note: the throttle should be added to the *end* of the list of throttles,
// so all NavigationThrottles that should be attached observe the
// WillStartRequest callback. RegisterThrottleForTesting has this behavior.
class TestNavigationManagerThrottle : public NavigationThrottle {
 public:
  TestNavigationManagerThrottle(
      NavigationThrottleRegistry& registry,
      base::OnceClosure on_will_start_request_closure,
      base::RepeatingClosure on_will_redirect_request_closure,
      base::OnceClosure on_will_process_response_closure,
      base::OnceClosure on_will_fail_request_closure)
      : NavigationThrottle(registry),
        on_will_start_request_closure_(
            std::move(on_will_start_request_closure)),
        on_will_redirect_request_closure_(
            std::move(on_will_redirect_request_closure)),
        on_will_process_response_closure_(
            std::move(on_will_process_response_closure)),
        on_will_fail_request_closure_(std::move(on_will_fail_request_closure)) {
  }
  ~TestNavigationManagerThrottle() override {}

  const char* GetNameForLogging() override {
    return "TestNavigationManagerThrottle";
  }

 private:
  // NavigationThrottle:
  NavigationThrottle::ThrottleCheckResult WillStartRequest() override {
    DCHECK(on_will_start_request_closure_);
    GetUIThreadTaskRunner({})->PostTask(
        FROM_HERE, std::move(on_will_start_request_closure_));
    return NavigationThrottle::DEFER;
  }

  NavigationThrottle::ThrottleCheckResult WillRedirectRequest() override {
    CHECK(on_will_redirect_request_closure_);
    GetUIThreadTaskRunner({})->PostTask(FROM_HERE,
                                        on_will_redirect_request_closure_);
    return NavigationThrottle::DEFER;
  }

  NavigationThrottle::ThrottleCheckResult WillProcessResponse() override {
    DCHECK(on_will_process_response_closure_);
    GetUIThreadTaskRunner({})->PostTask(
        FROM_HERE, std::move(on_will_process_response_closure_));
    return NavigationThrottle::DEFER;
  }

  NavigationThrottle::ThrottleCheckResult WillFailRequest() override {
    CHECK(on_will_fail_request_closure_);
    GetUIThreadTaskRunner({})->PostTask(
        FROM_HERE, std::move(on_will_fail_request_closure_));
    return NavigationThrottle::DEFER;
  }

  base::OnceClosure on_will_start_request_closure_;
  base::RepeatingClosure on_will_redirect_request_closure_;
  base::OnceClosure on_will_process_response_closure_;
  base::OnceClosure on_will_fail_request_closure_;
};

#if BUILDFLAG(IS_CHROMEOS)
void AppendGzippedResource(const base::RefCountedMemory& encoded,
                           std::string* to_append) {
  auto source_stream = std::make_unique<net::MockSourceStream>();
  source_stream->AddReadResult(base::span(encoded), net::OK,
                               net::MockSourceStream::SYNC);
  // Add an EOF.
  source_stream->AddReadResult(base::span<uint8_t>(), net::OK,
                               net::MockSourceStream::SYNC);
  std::unique_ptr<net::GzipSourceStream> filter = net::GzipSourceStream::Create(
      std::move(source_stream), net::SourceStreamType::kGzip);
  scoped_refptr<net::IOBufferWithSize> dest_buffer =
      base::MakeRefCounted<net::IOBufferWithSize>(4096);
  while (true) {
    int rv = filter->Read(dest_buffer.get(), dest_buffer->size(),
                          net::CompletionOnceCallback());
    ASSERT_LE(0, rv);
    if (rv <= 0) {
      break;
    }
    to_append->append(dest_buffer->data(), rv);
  }
}
#endif  // BUILDFLAG(IS_CHROMEOS)

// Queries for video input devices on the current system using the getSources
// API.
//
// This does not guarantee that a getUserMedia with video will succeed, as the
// camera could be busy for instance.
//
// Returns has-video-input-device to the test if there is a webcam available,
// no-video-input-devices otherwise.
const char kHasVideoInputDeviceOnSystem[] = R"(
    (function() {
      return navigator.mediaDevices.enumerateDevices()
      .then(function(devices) {
        if (devices.some((device) => device.kind == 'videoinput')) {
          return 'has-video-input-device';
        }
        return 'no-video-input-devices';
      });
    })()
)";

const char kHasVideoInputDevice[] = "has-video-input-device";

// Interceptor that replaces params.url with |new_url| and params.origin with
// |new_origin| for any commits to |target_url|.
class CommitOriginInterceptor : public DidCommitNavigationInterceptor {
 public:
  CommitOriginInterceptor(WebContents* web_contents,
                          const GURL& target_url,
                          const GURL& new_url,
                          const url::Origin& new_origin)
      : DidCommitNavigationInterceptor(web_contents),
        target_url_(target_url),
        new_url_(new_url),
        new_origin_(new_origin) {}

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

  ~CommitOriginInterceptor() override = default;

  // WebContentsObserver:
  void WebContentsDestroyed() override { delete this; }

 protected:
  bool WillProcessDidCommitNavigation(
      RenderFrameHost* render_frame_host,
      NavigationRequest* navigation_request,
      mojom::DidCommitProvisionalLoadParamsPtr* params,
      mojom::DidCommitProvisionalLoadInterfaceParamsPtr* interface_params)
      override {
    if ((**params).url == target_url_) {
      (**params).url = new_url_;
      (**params).origin = new_origin_;
    }
    return true;
  }

 private:
  GURL target_url_;
  GURL new_url_;
  url::Origin new_origin_;
};

// Observer which waits for a visual update in a RenderWidgetHost to meet some
// desired conditions.
class ResizeObserver : public RenderWidgetHostObserver {
 public:
  ResizeObserver(RenderWidgetHost* widget_host,
                 base::RepeatingCallback<bool()> is_complete_callback)
      : widget_host_(widget_host),
        is_complete_callback_(std::move(is_complete_callback)) {
    widget_host_->AddObserver(this);
  }

  ~ResizeObserver() override { widget_host_->RemoveObserver(this); }

  // RenderWidgetHostObserver:
  void RenderWidgetHostDidUpdateVisualProperties(
      RenderWidgetHost* widget_host) override {
    if (is_complete_callback_.Run()) {
      run_loop_.Quit();
    }
  }

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

 private:
  raw_ptr<RenderWidgetHost> widget_host_;
  base::RunLoop run_loop_;
  base::RepeatingCallback<bool()> is_complete_callback_;
};

// Observer for RenderFrameProxyHost by setting itself through
// RenderFrameProxyHost::SetObserverForTesting.
class ProxyHostObserver : public RenderFrameProxyHost::TestObserver {
 public:
  using CreatedCallback = base::RepeatingCallback<void(RenderFrameProxyHost*)>;

  ProxyHostObserver() = default;
  ~ProxyHostObserver() override = default;

  void Reset() { created_callback_ = CreatedCallback(); }

  void set_created_callback(CreatedCallback callback) {
    created_callback_ = std::move(callback);
  }

 private:
  // RenderFrameProxyHost::TestObserver:
  void OnCreated(RenderFrameProxyHost* rfph) override {
    if (created_callback_) {
      created_callback_.Run(rfph);
    }
  }

  // Callback which runs on RenderFrameProxyHost is created.
  CreatedCallback created_callback_;
};

ProxyHostObserver* GetProxyHostObserver() {
  static base::NoDestructor<ProxyHostObserver> observer;
  return observer.get();
}

bool IsRequestCompatibleWithSpeculativeRFH(NavigationRequest* request) {
  return request->state() <=
             NavigationRequest::NavigationState::WILL_PROCESS_RESPONSE &&
         request->GetAssociatedRFHType() ==
             NavigationRequest::AssociatedRenderFrameHostType::NONE;
}

}  // namespace

bool WaiterHelper::WaitInternal() {
  if (event_received_) {
    return true;
  }
  run_loop_.Run();
  return event_received_;
}

bool WaiterHelper::Wait() {
  bool result = WaitInternal();
  event_received_ = false;
  return result;
}

void WaiterHelper::OnEvent() {
  event_received_ = true;
  run_loop_.Quit();
}

bool NavigateToURL(WebContents* web_contents, const GURL& url) {
  return NavigateToURL(web_contents, url, url);
}

bool NavigateToURL(WebContents* web_contents,
                   const GURL& url,
                   const GURL& expected_commit_url) {
  NavigateToURLBlockUntilNavigationsComplete(
      web_contents, url, 1,
      /*ignore_uncommitted_navigations=*/false);
  if (!IsLastCommittedEntryOfPageType(web_contents, PAGE_TYPE_NORMAL)) {
    return false;
  }

  bool is_same_url = web_contents->GetLastCommittedURL() == expected_commit_url;
  if (!is_same_url) {
    DLOG(WARNING) << "Expected URL " << expected_commit_url << " but observed "
                  << web_contents->GetLastCommittedURL();
  }
  return is_same_url;
}

bool NavigateToURLFromRenderer(const ToRenderFrameHost& adapter,
                               const GURL& url) {
  return NavigateToURLFromRenderer(adapter, url, url);
}

bool NavigateToURLFromRenderer(const ToRenderFrameHost& adapter,
                               const GURL& url,
                               const GURL& expected_commit_url) {
  RenderFrameHost* rfh = adapter.render_frame_host();
  TestFrameNavigationObserver nav_observer(rfh);
  if (!BeginNavigateToURLFromRenderer(adapter, url)) {
    return false;
  }
  nav_observer.Wait();
  return nav_observer.last_committed_url() == expected_commit_url &&
         nav_observer.last_navigation_succeeded();
}

bool NavigateToURLFromRendererWithoutUserGesture(
    const ToRenderFrameHost& adapter,
    const GURL& url) {
  return NavigateToURLFromRendererWithoutUserGesture(adapter, url, url);
}

bool NavigateToURLFromRendererWithoutUserGesture(
    const ToRenderFrameHost& adapter,
    const GURL& url,
    const GURL& expected_commit_url) {
  RenderFrameHost* rfh = adapter.render_frame_host();
  TestFrameNavigationObserver nav_observer(rfh);
  if (!ExecJs(rfh, JsReplace("location = $1", url),
              EXECUTE_SCRIPT_NO_USER_GESTURE)) {
    return false;
  }
  nav_observer.Wait();
  return nav_observer.last_committed_url() == expected_commit_url;
}

bool BeginNavigateToURLFromRenderer(const ToRenderFrameHost& adapter,
                                    const GURL& url) {
  ExecuteScriptAsync(adapter, JsReplace("location = $1", url));
  DidStartNavigationObserver observer(
      WebContents::FromRenderFrameHost(adapter.render_frame_host()));
  observer.Wait();
  return observer.observed();
}

bool NavigateIframeToURL(WebContents* web_contents,
                         std::string_view iframe_id,
                         const GURL& url) {
  TestNavigationObserver load_observer(web_contents);
  bool result = BeginNavigateIframeToURL(web_contents, iframe_id, url);
  load_observer.Wait();
  return result;
}

bool BeginNavigateIframeToURL(WebContents* web_contents,
                              std::string_view iframe_id,
                              const GURL& url) {
  std::string script =
      base::StrCat({"setTimeout(\"var iframes = document.getElementById('",
                    iframe_id, "');iframes.src='", url.spec(), "';\",0)"});
  return ExecJs(web_contents, script, EXECUTE_SCRIPT_NO_USER_GESTURE);
}

void NavigateToURLBlockUntilNavigationsComplete(
    WebContents* web_contents,
    const GURL& url,
    int number_of_navigations,
    bool ignore_uncommitted_navigations) {
  // This mimics behavior of Shell::LoadURL...
  NavigationController::LoadURLParams params(url);
  params.transition_type = ui::PageTransitionFromInt(
      ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);

  NavigateToURLBlockUntilNavigationsComplete(web_contents, params,
                                             number_of_navigations,
                                             ignore_uncommitted_navigations);
}

void NavigateToURLBlockUntilNavigationsComplete(
    WebContents* web_contents,
    const NavigationController::LoadURLParams& params,
    int number_of_navigations,
    bool ignore_uncommitted_navigations) {
  // Prepare for the navigation.
  WaitForLoadStop(web_contents);
  TestNavigationObserver same_tab_observer(
      web_contents, number_of_navigations,
      MessageLoopRunner::QuitMode::IMMEDIATE,
      /*ignore_uncommitted_navigations=*/ignore_uncommitted_navigations);
  if (!blink::IsRendererDebugURL(params.url) && number_of_navigations == 1) {
    same_tab_observer.set_expected_initial_url(params.url);
  }

  web_contents->GetController().LoadURLWithParams(params);
  web_contents->GetOutermostWebContents()->Focus();

  // Wait until the expected number of navigations finish.
  same_tab_observer.Wait();
}

GURL GetFileUrlWithQuery(const base::FilePath& path,
                         std::string_view query_string) {
  GURL url = net::FilePathToFileURL(path);
  if (!query_string.empty()) {
    GURL::Replacements replacements;
    replacements.SetQueryStr(query_string);
    return url.ReplaceComponents(replacements);
  }
  return url;
}

void ResetTouchAction(RenderWidgetHost* host) {
  static_cast<input::InputRouterImpl*>(
      static_cast<RenderWidgetHostImpl*>(host)->input_router())
      ->ForceResetTouchActionForTest();
}

void RunUntilInputProcessed(RenderWidgetHost* host) {
  base::RunLoop run_loop;
  RenderWidgetHostImpl::From(host)->WaitForInputProcessed(
      run_loop.QuitClosure());
  run_loop.Run();
}

std::string ReferrerPolicyToString(
    network::mojom::ReferrerPolicy referrer_policy) {
  switch (referrer_policy) {
    case network::mojom::ReferrerPolicy::kDefault:
      return "no-meta";
    case network::mojom::ReferrerPolicy::kNoReferrerWhenDowngrade:
      return "no-referrer-when-downgrade";
    case network::mojom::ReferrerPolicy::kOrigin:
      return "origin";
    case network::mojom::ReferrerPolicy::kOriginWhenCrossOrigin:
      return "origin-when-crossorigin";
    case network::mojom::ReferrerPolicy::kSameOrigin:
      return "same-origin";
    case network::mojom::ReferrerPolicy::kStrictOrigin:
      return "strict-origin";
    case network::mojom::ReferrerPolicy::kAlways:
      return "always";
    case network::mojom::ReferrerPolicy::kNever:
      return "never";
    case network::mojom::ReferrerPolicy::kStrictOriginWhenCrossOrigin:
      return "strict-origin-when-cross-origin";
  }
  NOTREACHED();
}

mojo::PendingAssociatedReceiver<blink::mojom::FrameWidget>
BindFakeFrameWidgetInterfaces(RenderFrameHost* frame) {
  RenderWidgetHostImpl* render_widget_host_impl =
      static_cast<RenderFrameHostImpl*>(frame)->GetRenderWidgetHost();

  mojo::AssociatedRemote<blink::mojom::FrameWidgetHost> blink_frame_widget_host;
  auto blink_frame_widget_host_receiver =
      blink_frame_widget_host.BindNewEndpointAndPassDedicatedReceiver();

  mojo::AssociatedRemote<blink::mojom::FrameWidget> blink_frame_widget;
  auto blink_frame_widget_receiver =
      blink_frame_widget.BindNewEndpointAndPassDedicatedReceiver();

  render_widget_host_impl->BindFrameWidgetInterfaces(
      std::move(blink_frame_widget_host_receiver), blink_frame_widget.Unbind());

  return blink_frame_widget_receiver;
}

void SimulateActiveStateForWidget(RenderFrameHost* frame, bool active) {
  static_cast<RenderFrameHostImpl*>(frame)
      ->GetRenderWidgetHost()
      ->delegate()
      ->SendActiveState(active);
}

std::optional<uint64_t> GetVisitedLinkSaltForNavigation(
    NavigationHandle* navigation_handle) {
  return static_cast<NavigationRequest*>(navigation_handle)
      ->commit_params()
      .visited_link_salt;
}

void WaitForLoadStopWithoutSuccessCheck(WebContents* web_contents) {
  // In many cases, the load may have finished before we get here.  Only wait if
  // the tab still has a pending navigation.
  if (web_contents->IsLoading()) {
    LoadStopObserver load_stop_observer(web_contents);
    load_stop_observer.Wait();
  }
}

bool IsLastCommittedPageNormal(WebContents* web_contents) {
  bool is_page_normal =
      IsLastCommittedEntryOfPageType(web_contents, PAGE_TYPE_NORMAL);
  if (!is_page_normal) {
    NavigationEntry* last_entry =
        web_contents->GetController().GetLastCommittedEntry();
    if (last_entry) {
      LOG(ERROR) << "Http status code = " << last_entry->GetHttpStatusCode()
                 << ", page type = " << last_entry->GetPageType();
    } else {
      LOG(ERROR) << "No committed entry.";
    }
  }
  return is_page_normal;
}

bool WaitForLoadStop(WebContents* web_contents) {
  TRACE_EVENT0("test", "content::WaitForLoadStop");
  WebContentsDestroyedWatcher watcher(web_contents);
  WaitForLoadStopWithoutSuccessCheck(web_contents);
  if (watcher.IsDestroyed()) {
    LOG(ERROR) << "WebContents was destroyed during waiting for load stop.";
    return false;
  }
  return IsLastCommittedPageNormal(web_contents);
}

bool WaitForNavigationFinished(WebContents* web_contents,
                               TestNavigationObserver& observer) {
  TRACE_EVENT0("test", "content::WaitForNavigationFinished");
  WebContentsDestroyedWatcher watcher(web_contents);
  observer.WaitForNavigationFinished();
  if (watcher.IsDestroyed()) {
    LOG(ERROR)
        << "WebContents was destroyed during waiting for navigation finished.";
    return false;
  }
  return IsLastCommittedPageNormal(web_contents);
}

void PrepContentsForBeforeUnloadTest(WebContents* web_contents,
                                     bool trigger_user_activation) {
  web_contents->GetPrimaryMainFrame()->ForEachRenderFrameHost(
      [trigger_user_activation](RenderFrameHost* render_frame_host) {
        if (trigger_user_activation) {
          render_frame_host->ExecuteJavaScriptWithUserGestureForTests(
              std::u16string(), base::NullCallback(), ISOLATED_WORLD_ID_GLOBAL);
        }

        // Disable the hang monitor, otherwise there will be a race between
        // the beforeunload dialog and the beforeunload hang timer.
        render_frame_host->DisableBeforeUnloadHangMonitorForTesting();
      });
}

bool IsLastCommittedEntryOfPageType(WebContents* web_contents,
                                    PageType page_type) {
  NavigationEntry* last_entry =
      web_contents->GetController().GetLastCommittedEntry();
  return last_entry && last_entry->GetPageType() == page_type;
}

void OverrideLastCommittedOrigin(RenderFrameHost* render_frame_host,
                                 const url::Origin& origin) {
  static_cast<RenderFrameHostImpl*>(render_frame_host)
      ->SetLastCommittedOriginForTesting(origin);
}

void CrashTab(WebContents* web_contents) {
  RenderProcessHost* rph = web_contents->GetPrimaryMainFrame()->GetProcess();
  RenderProcessHostWatcher watcher(
      rph, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
  EXPECT_TRUE(rph->Shutdown(RESULT_CODE_KILLED));
  watcher.Wait();
  EXPECT_FALSE(watcher.did_exit_normally());
  EXPECT_TRUE(web_contents->IsCrashed());
}

void SimulateUnresponsivePrimaryMainFrameAndWaitForExit(
    WebContents* web_contents) {
  RenderProcessHost* rph = web_contents->GetPrimaryMainFrame()->GetProcess();
  RenderProcessHostWatcher watcher(
      rph, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);

  SimulateUnresponsiveRenderer(
      web_contents, web_contents->GetPrimaryMainFrame()->GetRenderWidgetHost());

  EXPECT_TRUE(rph->Shutdown(RESULT_CODE_HUNG));
  watcher.Wait();
  EXPECT_FALSE(watcher.did_exit_normally());
  EXPECT_TRUE(web_contents->IsCrashed());
}

void PwnCommitIPC(WebContents* web_contents,
                  const GURL& target_url,
                  const GURL& new_url,
                  const url::Origin& new_origin) {
  // This will be cleaned up when |web_contents| is destroyed.
  new CommitOriginInterceptor(web_contents, target_url, new_url, new_origin);
}

bool CanCommitURLForTesting(int child_id, const GURL& url) {
  auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
  return policy->CanCommitURL(child_id, url);
}

void SimulateUnresponsiveRenderer(WebContents* web_contents,
                                  RenderWidgetHost* widget) {
  static_cast<WebContentsImpl*>(web_contents)
      ->RendererUnresponsive(RenderWidgetHostImpl::From(widget),
                             base::DoNothing());
}

#if defined(USE_AURA)
bool IsResizeComplete(aura::test::WindowEventDispatcherTestApi* dispatcher_test,
                      RenderWidgetHostImpl* widget_host) {
  dispatcher_test->WaitUntilPointerMovesDispatched();
  widget_host->SynchronizeVisualProperties();
  return !widget_host->visual_properties_ack_pending_for_testing();
}

void WaitForResizeComplete(WebContents* web_contents) {
  aura::Window* content = web_contents->GetContentNativeView();
  if (!content) {
    return;
  }

  aura::WindowTreeHost* window_host = content->GetHost();
  aura::WindowEventDispatcher* dispatcher = window_host->dispatcher();
  aura::test::WindowEventDispatcherTestApi dispatcher_test(dispatcher);
  RenderWidgetHostImpl* widget_host = RenderWidgetHostImpl::From(
      web_contents->GetPrimaryMainFrame()->GetRenderViewHost()->GetWidget());
  if (!IsResizeComplete(&dispatcher_test, widget_host)) {
    ResizeObserver resize_observer(
        widget_host,
        base::BindRepeating(IsResizeComplete, &dispatcher_test, widget_host));
    resize_observer.Wait();
  }
}
#elif BUILDFLAG(IS_ANDROID)
bool IsResizeComplete(RenderWidgetHostImpl* widget_host) {
  return !widget_host->visual_properties_ack_pending_for_testing();
}

void WaitForResizeComplete(WebContents* web_contents) {
  RenderWidgetHostImpl* widget_host = RenderWidgetHostImpl::From(
      web_contents->GetRenderViewHost()->GetWidget());
  if (!IsResizeComplete(widget_host)) {
    ResizeObserver resize_observer(
        widget_host, base::BindRepeating(IsResizeComplete, widget_host));
    resize_observer.Wait();
  }
}
#endif

void NotifyCopyableViewInWebContents(WebContents* web_contents,
                                     base::OnceClosure done_callback) {
  NotifyCopyableViewInFrame(web_contents->GetPrimaryMainFrame(),
                            std::move(done_callback));
}

void NotifyCopyableViewInFrame(RenderFrameHost* render_frame_host,
                               base::OnceClosure done_callback) {
  RenderWidgetHostImpl* rwhi = static_cast<RenderWidgetHostImpl*>(
      render_frame_host->GetView()->GetRenderWidgetHost());

  // Note: this function intentionally avoids using RunLoops, which would make
  // the code easier to read, so that it can be used on Android which doesn't
  // support nested run loops.

  auto first_frame_done = base::BindOnce(
      [](base::WeakPtr<RenderWidgetHostImpl> rwhi,
         base::OnceClosure done_callback, bool success) {
        // This is invoked when the first `CompositorFrame` is submitted from
        // the renderer to the GPU. However, we want to wait until the Viz
        // process has received the new `CompositorFrame` so that the previously
        // submitted frame is available for copy. Waiting for a second frame to
        // be submitted guarantees this, since the second frame cannot be sent
        // until the first frame was ACKed by Viz.

        if (!rwhi || !success) {
          std::move(done_callback).Run();
          return;
        }

        // Force a redraw to ensure the callback below goes through the complete
        // compositing pipeline.
        rwhi->ForceRedrawForTesting();
        rwhi->InsertVisualStateCallback(base::BindOnce(
            [](base::WeakPtr<RenderWidgetHostImpl> rwhi,
               base::OnceClosure final_done_callback, bool success) {
              if (rwhi) {
                // `IsSurfaceAvailableForCopy` actually only checks if the
                // browser currently embeds a surface or not (as opposed to
                // sending a IPC to the GPU). However if the browser does not
                // embed any surface, we won't be able to issue any copy
                // requests.
                ASSERT_TRUE(rwhi->GetView()->IsSurfaceAvailableForCopy());
              }
              std::move(final_done_callback).Run();
            },
            rwhi->GetWeakPtr(), std::move(done_callback)));
      },
      rwhi->GetWeakPtr(), std::move(done_callback));

  rwhi->InsertVisualStateCallback(std::move(first_frame_done));
}

// TODO(crbug.com/40278950): Use
// `WebFrameWidgetImpl::NotifySwapAndPresentationTime` instead.
void WaitForCopyableViewInWebContents(WebContents* web_contents) {
  WaitForCopyableViewInFrame(web_contents->GetPrimaryMainFrame());
}

void WaitForCopyableViewInFrame(RenderFrameHost* render_frame_host) {
  base::test::TestFuture<void> future;
  NotifyCopyableViewInFrame(render_frame_host, future.GetCallback());
  CHECK(future.Wait());
}

void SimulateEndOfPaintHoldingOnPrimaryMainFrame(WebContents* web_contents) {
  WebContentsImpl* web_contents_impl =
      static_cast<WebContentsImpl*>(web_contents);
  RenderWidgetHostImpl* main_frame_rwh =
      web_contents_impl->GetPrimaryMainFrame()->GetRenderWidgetHost();
  main_frame_rwh->ForceFirstFrameAfterNavigationTimeout();
}

void SimulateMouseClick(WebContents* web_contents,
                        int modifiers,
                        blink::WebMouseEvent::Button button) {
  int x = web_contents->GetContainerBounds().width() / 2;
  int y = web_contents->GetContainerBounds().height() / 2;
  SimulateMouseClickAt(web_contents, modifiers, button, gfx::Point(x, y));
}

void SimulateMouseClickAt(WebContents* web_contents,
                          int modifiers,
                          blink::WebMouseEvent::Button button,
                          const gfx::Point& point) {
  auto* web_contents_impl = static_cast<WebContentsImpl*>(web_contents);
  auto* rwhvb = static_cast<RenderWidgetHostViewBase*>(
      web_contents->GetRenderWidgetHostView());
  blink::WebMouseEvent mouse_event(blink::WebInputEvent::Type::kMouseDown,
                                   modifiers, ui::EventTimeForNow());
  mouse_event.button = button;
  mouse_event.SetPositionInWidget(point.x(), point.y());
  // Mac needs positionInScreen for events to plugins.
  gfx::Rect offset = web_contents->GetContainerBounds();
  mouse_event.SetPositionInScreen(point.x() + offset.x(),
                                  point.y() + offset.y());
  mouse_event.click_count = 1;
  web_contents_impl->GetInputEventRouter()->RouteMouseEvent(rwhvb, &mouse_event,
                                                            ui::LatencyInfo());
  mouse_event.SetType(blink::WebInputEvent::Type::kMouseUp);
  web_contents_impl->GetInputEventRouter()->RouteMouseEvent(rwhvb, &mouse_event,
                                                            ui::LatencyInfo());
}

gfx::PointF GetCenterCoordinatesOfElementWithId(
    const ToRenderFrameHost& adapter,
    std::string_view id) {
  float x =
      EvalJs(adapter, JsReplace("const bounds = "
                                "document.getElementById($1)."
                                "getBoundingClientRect();"
                                "Math.floor(bounds.left + bounds.width / 2)",
                                id))
          .ExtractDouble();
  float y =
      EvalJs(adapter, JsReplace("const bounds = "
                                "document.getElementById($1)."
                                "getBoundingClientRect();"
                                "Math.floor(bounds.top + bounds.height / 2)",
                                id))
          .ExtractDouble();
  return gfx::PointF(x, y);
}

void SimulateMouseClickOrTapElementWithId(WebContents* web_contents,
                                          std::string_view id) {
  gfx::Point point = gfx::ToFlooredPoint(
      GetCenterCoordinatesOfElementWithId(web_contents, id));

#if BUILDFLAG(IS_ANDROID)
  SimulateTapDownAt(web_contents, point);
  SimulateTapAt(web_contents, point);
#else
  SimulateMouseClickAt(web_contents, 0, blink::WebMouseEvent::Button::kLeft,
                       point);
#endif  // BUILDFLAG(IS_ANDROID)
}

void SimulateMouseEvent(WebContents* web_contents,
                        blink::WebInputEvent::Type type,
                        const gfx::Point& point) {
  SimulateMouseEvent(web_contents, type,
                     blink::WebMouseEvent::Button::kNoButton, point);
}

void SimulateMouseEvent(WebContents* web_contents,
                        blink::WebInputEvent::Type type,
                        blink::WebMouseEvent::Button button,
                        const gfx::Point& point) {
  auto* web_contents_impl = static_cast<WebContentsImpl*>(web_contents);
  auto* rwhvb = static_cast<RenderWidgetHostViewBase*>(
      web_contents->GetRenderWidgetHostView());
  blink::WebMouseEvent mouse_event(type, 0, ui::EventTimeForNow());
  mouse_event.button = button;
  mouse_event.SetPositionInWidget(point.x(), point.y());
  // Mac needs positionInScreen for events to plugins.
  gfx::Rect offset = web_contents->GetContainerBounds();
  mouse_event.SetPositionInScreen(point.x() + offset.x(),
                                  point.y() + offset.y());

  web_contents_impl->GetInputEventRouter()->RouteMouseEvent(rwhvb, &mouse_event,
                                                            ui::LatencyInfo());
}

void SimulateMouseWheelEvent(WebContents* web_contents,
                             const gfx::Point& point,
                             const gfx::Vector2d& delta,
                             const blink::WebMouseWheelEvent::Phase phase) {
  blink::WebMouseWheelEvent wheel_event(blink::WebInputEvent::Type::kMouseWheel,
                                        blink::WebInputEvent::kNoModifiers,
                                        ui::EventTimeForNow());

  wheel_event.SetPositionInWidget(point.x(), point.y());
  wheel_event.delta_x = delta.x();
  wheel_event.delta_y = delta.y();
  wheel_event.phase = phase;
  RenderWidgetHostImpl* widget_host = RenderWidgetHostImpl::From(
      web_contents->GetPrimaryMainFrame()->GetRenderViewHost()->GetWidget());
  widget_host->ForwardWheelEvent(wheel_event);
}

#if !BUILDFLAG(IS_MAC)
void SimulateMouseWheelCtrlZoomEvent(RenderWidgetHost* render_widget_host,
                                     const gfx::Point& point,
                                     bool zoom_in,
                                     blink::WebMouseWheelEvent::Phase phase) {
  blink::WebMouseWheelEvent wheel_event(blink::WebInputEvent::Type::kMouseWheel,
                                        blink::WebInputEvent::kControlKey,
                                        ui::EventTimeForNow());

  wheel_event.SetPositionInWidget(point.x(), point.y());
  wheel_event.delta_units = ui::ScrollGranularity::kScrollByPrecisePixel;
  wheel_event.delta_y =
      (zoom_in ? 1.0 : -1.0) * ui::MouseWheelEvent::kWheelDelta;
  wheel_event.wheel_ticks_y = (zoom_in ? 1.0 : -1.0);
  wheel_event.phase = phase;
  RenderWidgetHostImpl* widget_host =
      RenderWidgetHostImpl::From(render_widget_host);
  widget_host->ForwardWheelEvent(wheel_event);
}

void SimulateTouchscreenPinch(WebContents* web_contents,
                              const gfx::PointF& anchor,
                              float scale_change,
                              base::OnceClosure on_complete) {
  SyntheticPinchGestureParams params;
  params.gesture_source_type = mojom::GestureSourceType::kTouchInput;
  params.scale_factor = scale_change;
  params.anchor = anchor;

  auto pinch_gesture =
      std::make_unique<SyntheticTouchscreenPinchGesture>(params);
  RenderWidgetHostImpl* widget_host = RenderWidgetHostImpl::From(
      web_contents->GetTopLevelRenderWidgetHostView()->GetRenderWidgetHost());
  widget_host->QueueSyntheticGesture(
      std::move(pinch_gesture),
      base::BindOnce(
          [](base::OnceClosure on_complete, SyntheticGesture::Result result) {
            std::move(on_complete).Run();
          },
          std::move(on_complete)));
}

#endif  // !BUILDFLAG(IS_MAC)

void SimulateGesturePinchSequence(RenderWidgetHost* render_widget_host,
                                  const gfx::Point& point,
                                  float scale,
                                  blink::WebGestureDevice source_device) {
  RenderWidgetHostImpl* widget_host =
      RenderWidgetHostImpl::From(render_widget_host);

  blink::WebGestureEvent pinch_begin(
      blink::WebInputEvent::Type::kGesturePinchBegin,
      blink::WebInputEvent::kNoModifiers, ui::EventTimeForNow(), source_device);
  pinch_begin.SetPositionInWidget(gfx::PointF(point));
  pinch_begin.SetPositionInScreen(gfx::PointF(point));
  pinch_begin.SetNeedsWheelEvent(source_device ==
                                 blink::WebGestureDevice::kTouchpad);
  widget_host->ForwardGestureEvent(pinch_begin);

  blink::WebGestureEvent pinch_update(pinch_begin);
  pinch_update.SetType(blink::WebInputEvent::Type::kGesturePinchUpdate);
  pinch_update.data.pinch_update.scale = scale;
  pinch_update.SetNeedsWheelEvent(source_device ==
                                  blink::WebGestureDevice::kTouchpad);
  widget_host->ForwardGestureEvent(pinch_update);

  blink::WebGestureEvent pinch_end(pinch_begin);
  pinch_end.SetType(blink::WebInputEvent::Type::kGesturePinchEnd);
  pinch_end.SetNeedsWheelEvent(source_device ==
                               blink::WebGestureDevice::kTouchpad);
  widget_host->ForwardGestureEvent(pinch_end);
}

void SimulateGesturePinchSequence(WebContents* web_contents,
                                  const gfx::Point& point,
                                  float scale,
                                  blink::WebGestureDevice source_device) {
  RenderWidgetHost* widget_host =
      web_contents->GetPrimaryMainFrame()->GetRenderWidgetHost();
  SimulateGesturePinchSequence(widget_host, point, scale, source_device);
}

void SimulateGestureScrollSequence(RenderWidgetHost* render_widget_host,
                                   const gfx::Point& point,
                                   const gfx::Vector2dF& delta) {
  blink::WebGestureEvent scroll_begin(
      blink::WebGestureEvent::Type::kGestureScrollBegin,
      blink::WebInputEvent::kNoModifiers, ui::EventTimeForNow(),
      blink::WebGestureDevice::kTouchpad);
  scroll_begin.SetPositionInWidget(gfx::PointF(point));
  scroll_begin.data.scroll_begin.delta_x_hint = delta.x();
  scroll_begin.data.scroll_begin.delta_y_hint = delta.y();
  render_widget_host->ForwardGestureEvent(scroll_begin);

  blink::WebGestureEvent scroll_update(
      blink::WebGestureEvent::Type::kGestureScrollUpdate,
      blink::WebInputEvent::kNoModifiers, ui::EventTimeForNow(),
      blink::WebGestureDevice::kTouchpad);
  scroll_update.SetPositionInWidget(gfx::PointF(point));
  scroll_update.data.scroll_update.delta_x = delta.x();
  scroll_update.data.scroll_update.delta_y = delta.y();
  render_widget_host->ForwardGestureEvent(scroll_update);

  blink::WebGestureEvent scroll_end(
      blink::WebGestureEvent::Type::kGestureScrollEnd,
      blink::WebInputEvent::kNoModifiers, ui::EventTimeForNow(),
      blink::WebGestureDevice::kTouchpad);
  scroll_end.SetPositionInWidget(gfx::PointF(point));
  render_widget_host->ForwardGestureEvent(scroll_end);
}

void SimulateGestureScrollSequence(WebContents* web_contents,
                                   const gfx::Point& point,
                                   const gfx::Vector2dF& delta) {
  RenderWidgetHostImpl* widget_host = RenderWidgetHostImpl::From(
      web_contents->GetPrimaryMainFrame()->GetRenderWidgetHost());

  SimulateGestureScrollSequence(widget_host, point, delta);
}

void SimulateGestureEvent(RenderWidgetHost* render_widget_host,
                          const blink::WebGestureEvent& gesture_event,
                          const ui::LatencyInfo& latency) {
  RenderWidgetHostViewBase* view =
      static_cast<RenderWidgetHostViewBase*>(render_widget_host->GetView());
  view->ProcessGestureEvent(gesture_event, latency);
}

void SimulateGestureEvent(WebContents* web_contents,
                          const blink::WebGestureEvent& gesture_event,
                          const ui::LatencyInfo& latency) {
  RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
      web_contents->GetRenderWidgetHostView());
  view->ProcessGestureEvent(gesture_event, latency);
}

void SimulateTouchGestureAt(WebContents* web_contents,
                            const gfx::Point& point,
                            blink::WebInputEvent::Type type) {
  blink::WebGestureEvent gesture(type, 0, ui::EventTimeForNow(),
                                 blink::WebGestureDevice::kTouchscreen);
  gesture.SetPositionInWidget(gfx::PointF(point));
  RenderWidgetHostImpl* widget_host = RenderWidgetHostImpl::From(
      web_contents->GetPrimaryMainFrame()->GetRenderViewHost()->GetWidget());
  widget_host->ForwardGestureEvent(gesture);
}

void SimulateTapDownAt(WebContents* web_contents, const gfx::Point& point) {
  SimulateTouchGestureAt(web_contents, point,
                         blink::WebGestureEvent::Type::kGestureTapDown);
}

void SimulateTapAt(WebContents* web_contents, const gfx::Point& point) {
  SimulateTouchGestureAt(web_contents, point,
                         blink::WebGestureEvent::Type::kGestureTap);
}

void SimulateTapWithModifiersAt(WebContents* web_contents,
                                unsigned modifiers,
                                const gfx::Point& point) {
  blink::WebGestureEvent tap(blink::WebGestureEvent::Type::kGestureTap,
                             modifiers, ui::EventTimeForNow(),
                             blink::WebGestureDevice::kTouchpad);
  tap.SetPositionInWidget(gfx::PointF(point));
  RenderWidgetHostImpl* widget_host = RenderWidgetHostImpl::From(
      web_contents->GetPrimaryMainFrame()->GetRenderViewHost()->GetWidget());
  widget_host->ForwardGestureEvent(tap);
}

#if defined(USE_AURA)
void SimulateTouchEventAt(WebContents* web_contents,
                          ui::EventType event_type,
                          const gfx::Point& point) {
  ui::TouchEvent touch(event_type, point, base::TimeTicks(),
                       ui::PointerDetails(ui::EventPointerType::kTouch, 0));
  static_cast<RenderWidgetHostViewAura*>(
      web_contents->GetRenderWidgetHostView())
      ->OnTouchEvent(&touch);
}

void SimulateLongTapAt(WebContents* web_contents, const gfx::Point& point) {
  RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
      web_contents->GetRenderWidgetHostView());

  ui::TouchEvent touch_start(
      ui::EventType::kTouchPressed, point, base::TimeTicks(),
      ui::PointerDetails(ui::EventPointerType::kTouch, 0));
  rwhva->OnTouchEvent(&touch_start);

  ui::GestureEventDetails tap_down_details(ui::EventType::kGestureTapDown);
  tap_down_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHSCREEN);
  ui::GestureEvent tap_down(point.x(), point.y(), 0, ui::EventTimeForNow(),
                            tap_down_details, touch_start.unique_event_id());
  rwhva->OnGestureEvent(&tap_down);

  ui::GestureEventDetails long_press_details(ui::EventType::kGestureLongPress);
  long_press_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHSCREEN);
  ui::GestureEvent long_press(point.x(), point.y(), 0, ui::EventTimeForNow(),
                              long_press_details,
                              touch_start.unique_event_id());
  rwhva->OnGestureEvent(&long_press);

  ui::TouchEvent touch_end(ui::EventType::kTouchReleased, point,
                           base::TimeTicks(),
                           ui::PointerDetails(ui::EventPointerType::kTouch, 0));
  rwhva->OnTouchEvent(&touch_end);

  ui::GestureEventDetails long_tap_details(ui::EventType::kGestureLongTap);
  long_tap_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHSCREEN);
  ui::GestureEvent long_tap(point.x(), point.y(), 0, ui::EventTimeForNow(),
                            long_tap_details, touch_end.unique_event_id());
  rwhva->OnGestureEvent(&long_tap);
}

// Observer which waits for the selection bounds in a RenderWidgetHostViewAura
// to meet some desired conditions.
class SelectionBoundsWaiter : public TextInputManager::Observer {
 public:
  using Predicate = base::RepeatingCallback<bool()>;

  SelectionBoundsWaiter(RenderWidgetHostViewAura* rwhva, Predicate predicate)
      : predicate_(std::move(predicate)) {
    text_input_manager_observation_.Observe(rwhva->GetTextInputManager());
  }
  SelectionBoundsWaiter(const SelectionBoundsWaiter&) = delete;
  SelectionBoundsWaiter& operator=(const SelectionBoundsWaiter&) = delete;
  virtual ~SelectionBoundsWaiter() = default;

  // TextInputManager::Observer:
  void OnSelectionBoundsChanged(
      TextInputManager* text_input_manager,
      RenderWidgetHostViewBase* updated_view) override {
    if (predicate_.Run()) {
      run_loop_.Quit();
    }
  }

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

 private:
  base::RunLoop run_loop_;
  Predicate predicate_;
  base::ScopedObservation<TextInputManager, TextInputManager::Observer>
      text_input_manager_observation_{this};
};

NonZeroCaretSizeWaiter::NonZeroCaretSizeWaiter(WebContents* web_contents) {
  RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
      web_contents->GetRenderWidgetHostView());
  selection_bounds_waiter_ = std::make_unique<SelectionBoundsWaiter>(
      rwhva, base::BindLambdaForTesting([rwhva]() {
        return !rwhva->GetCaretBounds().size().IsZero();
      }));
}

NonZeroCaretSizeWaiter::~NonZeroCaretSizeWaiter() = default;

void NonZeroCaretSizeWaiter::Wait() {
  selection_bounds_waiter_->Wait();
}

CaretBoundsUpdateWaiter::CaretBoundsUpdateWaiter(WebContents* web_contents) {
  RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
      web_contents->GetRenderWidgetHostView());
  const gfx::Rect current_caret_bounds = rwhva->GetCaretBounds();
  selection_bounds_waiter_ = std::make_unique<SelectionBoundsWaiter>(
      rwhva, base::BindLambdaForTesting([rwhva, current_caret_bounds]() {
        return rwhva->GetCaretBounds() != current_caret_bounds;
      }));
}

CaretBoundsUpdateWaiter::~CaretBoundsUpdateWaiter() = default;

void CaretBoundsUpdateWaiter::Wait() {
  selection_bounds_waiter_->Wait();
}

BoundingBoxUpdateWaiter::BoundingBoxUpdateWaiter(WebContents* web_contents) {
  RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
      web_contents->GetRenderWidgetHostView());
  const gfx::Rect current_bounding_box = rwhva->GetSelectionBoundingBox();
  selection_bounds_waiter_ = std::make_unique<SelectionBoundsWaiter>(
      rwhva, base::BindLambdaForTesting([rwhva, current_bounding_box]() {
        return rwhva->GetSelectionBoundingBox() != current_bounding_box;
      }));
}

BoundingBoxUpdateWaiter::~BoundingBoxUpdateWaiter() = default;

void BoundingBoxUpdateWaiter::Wait() {
  selection_bounds_waiter_->Wait();
}
#endif

double GetPendingZoomLevel(RenderWidgetHost* render_widget_host) {
  auto* rwhi = static_cast<RenderWidgetHostImpl*>(render_widget_host);
  return WebContentsImpl::FromRenderWidgetHostImpl(rwhi)->GetPendingZoomLevel(
      rwhi);
}

void SimulateKeyPress(WebContents* web_contents,
                      ui::DomKey key,
                      ui::DomCode code,
                      ui::KeyboardCode key_code,
                      bool control,
                      bool shift,
                      bool alt,
                      bool command) {
  SimulateKeyPressImpl(web_contents, key, code, key_code, control, shift, alt,
                       command, /*send_char=*/true);
}

void SimulateKeyPressWithoutChar(WebContents* web_contents,
                                 ui::DomKey key,
                                 ui::DomCode code,
                                 ui::KeyboardCode key_code,
                                 bool control,
                                 bool shift,
                                 bool alt,
                                 bool command) {
  SimulateKeyPressImpl(web_contents, key, code, key_code, control, shift, alt,
                       command, /*send_char=*/false);
}

void SimulateProxyHostPostMessage(RenderFrameHost* source_render_frame_host,
                                  RenderFrameHost* target_render_frame_host,
                                  blink::TransferableMessage message) {
  RenderFrameProxyHost* proxy_host =
      static_cast<RenderFrameHostImpl*>(target_render_frame_host)
          ->browsing_context_state()
          ->GetRenderFrameProxyHost(
              static_cast<SiteInstanceImpl*>(
                  source_render_frame_host->GetSiteInstance())
                  ->group());
  CHECK(proxy_host);

  proxy_host->RouteMessageEvent(
      source_render_frame_host->GetFrameToken(),
      source_render_frame_host->GetLastCommittedOrigin(),
      target_render_frame_host->GetLastCommittedOrigin(), std::move(message));
}

ScopedSimulateModifierKeyPress::ScopedSimulateModifierKeyPress(
    WebContents* web_contents,
    bool control,
    bool shift,
    bool alt,
    bool command)
    : web_contents_(web_contents),
      modifiers_(0),
      control_(control),
      shift_(shift),
      alt_(alt),
      command_(command) {
  modifiers_ =
      SimulateModifierKeysDown(web_contents_, control_, shift_, alt_, command_);
}

ScopedSimulateModifierKeyPress::~ScopedSimulateModifierKeyPress() {
  modifiers_ = SimulateModifierKeysUp(web_contents_, control_, shift_, alt_,
                                      command_, modifiers_);
  DCHECK_EQ(0, modifiers_);
}

void ScopedSimulateModifierKeyPress::MouseClickAt(
    int additional_modifiers,
    blink::WebMouseEvent::Button button,
    const gfx::Point& point) {
  SimulateMouseClickAt(web_contents_, modifiers_ | additional_modifiers, button,
                       point);
}

void ScopedSimulateModifierKeyPress::KeyPress(ui::DomKey key,
                                              ui::DomCode code,
                                              ui::KeyboardCode key_code) {
  SimulateKeyEvent(web_contents_, key, code, key_code, /*send_char=*/true,
                   modifiers_);
}

void ScopedSimulateModifierKeyPress::KeyPressWithoutChar(
    ui::DomKey key,
    ui::DomCode code,
    ui::KeyboardCode key_code) {
  SimulateKeyEvent(web_contents_, key, code, key_code, /*send_char=*/false,
                   modifiers_);
}

bool IsWebcamAvailableOnSystem(WebContents* web_contents) {
  return EvalJs(web_contents, kHasVideoInputDeviceOnSystem).ExtractString() ==
         kHasVideoInputDevice;
}

RenderFrameHost* ConvertToRenderFrameHost(WebContents* web_contents) {
  return web_contents->GetPrimaryMainFrame();
}

RenderFrameHost* ConvertToRenderFrameHost(RenderFrameHost* render_frame_host) {
  return render_frame_host;
}

void ExecuteScriptAsync(const ToRenderFrameHost& adapter,
                        std::string_view script) {
  // Prerendering pages will never have user gesture.
  if (adapter.render_frame_host()->GetLifecycleState() ==
      RenderFrameHost::LifecycleState::kPrerendering) {
    ExecuteScriptAsyncWithoutUserGesture(adapter, script);
  } else {
    adapter.render_frame_host()->ExecuteJavaScriptWithUserGestureForTests(
        base::UTF8ToUTF16(script), base::NullCallback(),
        ISOLATED_WORLD_ID_GLOBAL);
  }
}

void ExecuteScriptAsyncWithoutUserGesture(const ToRenderFrameHost& adapter,
                                          std::string_view script) {
  adapter.render_frame_host()->ExecuteJavaScriptForTests(
      base::UTF8ToUTF16(script), base::NullCallback(),
      ISOLATED_WORLD_ID_GLOBAL);
}

// EvalJsResult methods.
EvalJsResult::EvalJsResult(base::Value value, std::string_view error)
    : data_(error.empty() ? std::variant<std::string, base::Value>(
                                std::in_place_type_t<base::Value>(),
                                std::move(value))
                          : std::variant<std::string, base::Value>(
                                std::in_place_type_t<std::string>(),
                                error)) {}

EvalJsResult::EvalJsResult(const EvalJsResult& other)
    : data_(std::visit(
          absl::Overload{
              [](const std::string& error)
                  -> std::variant<std::string, base::Value> { return error; },
              [](const base::Value& value)
                  -> std::variant<std::string, base::Value> {
                return value.Clone();
              },
          },
          other.data_)) {}

EvalJsResult& EvalJsResult::operator=(const EvalJsResult& other) {
  data_ = std::visit(
      absl::Overload{
          [](const std::string& error)
              -> std::variant<std::string, base::Value> { return error; },
          [](const base::Value& value)
              -> std::variant<std::string, base::Value> {
            return value.Clone();
          },
      },
      other.data_);
  return *this;
}

EvalJsResult::EvalJsResult(EvalJsResult&&) = default;

EvalJsResult& EvalJsResult::operator=(EvalJsResult&&) = default;

EvalJsResult::~EvalJsResult() = default;

const std::string& EvalJsResult::ExtractString() const {
  CHECK(is_ok())
      << "Can't ExtractString() because the script encountered a problem: "
      << *error();
  CHECK(value()->is_string())
      << "Can't ExtractString() because script result: " << *value()
      << "is not a string.";
  return value()->GetString();
}

int EvalJsResult::ExtractInt() const {
  CHECK(is_ok())
      << "Can't ExtractInt() because the script encountered a problem: "
      << *error();
  CHECK(value()->is_int()) << "Can't ExtractInt() because script result: "
                           << *value() << "is not an int.";
  return value()->GetInt();
}

bool EvalJsResult::ExtractBool() const {
  CHECK(is_ok())
      << "Can't ExtractBool() because the script encountered a problem: "
      << *error();
  CHECK(value()->is_bool())
      << "Can't ExtractBool() because script result: " << *value()
      << "is not a bool.";
  return value()->GetBool();
}

double EvalJsResult::ExtractDouble() const {
  CHECK(is_ok())
      << "Can't ExtractDouble() because the script encountered a problem: "
      << *error();
  CHECK(value()->is_double() || value()->is_int())
      << "Can't ExtractDouble() because script result: " << *value()
      << "is not a double or int.";
  return value()->GetDouble();
}

const base::Value::List& EvalJsResult::ExtractList() const {
  CHECK(is_ok())
      << "Can't ExtractList() because the script encountered a problem: "
      << *error();
  CHECK(value()->is_list())
      << "Can't ExtractList() because script result: " << *value()
      << "is not a list.";
  return value()->GetList();
}

const base::Value::Dict& EvalJsResult::ExtractDict() const {
  CHECK(is_ok())
      << "Can't ExtractDict() because the script encountered a problem: "
      << *error();
  CHECK(value()->is_dict())
      << "Can't ExtractDict() because script result: " << *value()
      << "is not a dictionary.";
  return value()->GetDict();
}

const std::string& EvalJsResult::ExtractError() const {
  CHECK(!is_ok()) << "Can't ExtractError() because the script did not fail: "
                  << *value();
  return error().value();
}

std::ostream& operator<<(std::ostream& os, const EvalJsResult& bar) {
  if (!bar.is_ok()) {
    os << bar.ExtractError();
  } else {
    os << *bar.value();
  }
  return os;
}

namespace {

// Parse a JS stack trace out of |js_error|, detect frames that match
// |source_name|, and interleave the appropriate lines of source code from
// |source| into the error report. This is meant to be useful for scripts that
// are passed to ExecJs/EvalJs functions, and hence dynamically generated.
//
// An adjustment of |column_adjustment_for_line_one| characters is subtracted
// when mapping positions from line 1 of |source|. This is to offset the effect
// of boilerplate added by the script runner.
//
// TODO(nick): Elide snippets to 80 chars, since it is common for sources to not
// include newlines.
std::string AnnotateAndAdjustJsStackTraces(std::string_view js_error,
                                           std::string source_name,
                                           std::string_view source,
                                           int column_adjustment_for_line_one) {
  // Escape wildcards in |source_name| for use in MatchPattern.
  base::ReplaceChars(source_name, "\\", "\\\\", &source_name);
  base::ReplaceChars(source_name, "*", "\\*", &source_name);
  base::ReplaceChars(source_name, "?", "\\?", &source_name);

  // This vector maps line numbers to the corresponding text in |source|.
  const std::vector<std::string_view> source_lines = base::SplitStringPiece(
      source, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);

  // |source_frame_pattern| should match any line that looks like a stack frame
  // from a source file named |source_name|.
  const std::string source_frame_pattern =
      base::StringPrintf("    at *%s:*:*", source_name.c_str());

  // This is the amount of indentation that is applied to the lines of inserted
  // annotations.
  const std::string indent(8, ' ');
  const std::string_view elision_mark = "";

  // Loop over each line of |js_error|, and append each to |annotated_error| --
  // possibly rewriting to include extra context.
  std::ostringstream annotated_error;
  for (std::string_view error_line : base::SplitStringPiece(
           js_error, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL)) {
    // Does this look like a stack frame whose URL source matches |source_name|?
    if (base::MatchPattern(error_line, source_frame_pattern)) {
      // When a match occurs, annotate the stack trace with the corresponding
      // line from |source|, along with a ^^^ underneath, indicating the column
      // position.
      std::vector<std::string_view> error_line_parts = base::SplitStringPiece(
          error_line, ":", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
      CHECK_GE(error_line_parts.size(), 2u);

      int column_number = 0;
      base::StringToInt(error_line_parts.back(), &column_number);
      error_line_parts.pop_back();
      int line_number = 0;
      base::StringToInt(error_line_parts.back(), &line_number);
      error_line_parts.pop_back();

      // Protect against out-of-range matches.
      if ((line_number > 0) && (column_number > 0) &&
          static_cast<size_t>(line_number) <= source_lines.size()) {
        // Apply adjustment requested by caller to columns on the first line.
        // This allows us to add preamble boilerplate to the script, but still
        // locate errors correctly.
        if (line_number == 1 &&
            column_number > column_adjustment_for_line_one) {
          column_number -= column_adjustment_for_line_one;
        }

        // Some source lines are huge. Elide |source_line| so that it doesn't
        // occupy more than one actual line.
        std::string source_line(source_lines[line_number - 1]);

        int max_column_number = 60 - indent.length();
        if (column_number > max_column_number) {
          source_line = source_line.substr(column_number - max_column_number);
          column_number = max_column_number;
          source_line.replace(0, elision_mark.length(), elision_mark.data(),
                              elision_mark.length());
        }

        size_t max_length = 80 - indent.length();
        if (source_line.length() > max_length) {
          source_line = base::StrCat(
              {source_line.substr(0, max_length - elision_mark.length()),
               elision_mark});
        }

        annotated_error << base::JoinString(error_line_parts, ":") << ":"
                        << line_number << ":" << column_number << "):\n"
                        << indent << source_line << '\n'
                        << indent << std::string(column_number - 1, ' ')
                        << "^^^^^\n";
        continue;
      }
    }
    // This line was not rewritten -- just append it as-is.
    annotated_error << error_line << "\n";
  }
  return annotated_error.str();
}

// Waits for a response from ExecuteJavaScriptForTests, simulating an
// error if the target renderer is destroyed while executing the script.
class ExecuteJavaScriptForTestsWaiter : public WebContentsObserver {
 public:
  explicit ExecuteJavaScriptForTestsWaiter(const ToRenderFrameHost& adapter)
      : WebContentsObserver(
            WebContents::FromRenderFrameHost(adapter.render_frame_host())),
        render_frame_host_(adapter.render_frame_host()) {}

  blink::mojom::LocalFrame::JavaScriptExecuteRequestForTestsCallback
  GetCallback() {
    return base::BindOnce(&ExecuteJavaScriptForTestsWaiter::SetValue,
                          weak_ptr_factory_.GetWeakPtr());
  }

  bool Wait() {
    if (!has_value_) {
      run_loop_.Run();
    }
    return has_value_;
  }

  blink::mojom::JavaScriptExecutionResultType GetResultType() {
    DCHECK(has_value_);
    return type_;
  }

  const base::Value& GetResult() {
    DCHECK(has_value_);
    return value_;
  }

  // WebContentsObserver
  void PrimaryMainFrameRenderProcessGone(
      base::TerminationStatus status) override {
    if (status == base::TERMINATION_STATUS_NORMAL_TERMINATION ||
        status == base::TERMINATION_STATUS_STILL_RUNNING) {
      return;
    }
    UpdateAfterScriptFailed("Renderer terminated.");
  }
  void RenderFrameDeleted(RenderFrameHost* render_frame_host) override {
    if (render_frame_host_ != render_frame_host) {
      return;
    }
    UpdateAfterScriptFailed("RenderFrame deleted.");
  }

 private:
  void UpdateAfterScriptFailed(const std::string& msg) {
    render_frame_host_ = nullptr;
    if (has_value_) {
      return;
    }
    SetValue(blink::mojom::JavaScriptExecutionResultType::kException,
             base::Value(msg));
  }

  void SetValue(blink::mojom::JavaScriptExecutionResultType type,
                base::Value value) {
    DCHECK(!has_value_);
    has_value_ = true;
    type_ = type;
    value_ = value.Clone();
    run_loop_.Quit();
  }

  raw_ptr<RenderFrameHost> render_frame_host_;
  base::RunLoop run_loop_{base::RunLoop::Type::kNestableTasksAllowed};
  bool has_value_ = false;
  blink::mojom::JavaScriptExecutionResultType type_;
  base::Value value_;

  base::WeakPtrFactory<ExecuteJavaScriptForTestsWaiter> weak_ptr_factory_{this};
};

EvalJsResult EvalJsRunner(
    const ToRenderFrameHost& execution_target,
    std::string_view script,
    std::string_view source_url,
    int options,
    int32_t world_id,
    base::OnceClosure after_script_invoke = base::DoNothing()) {
  RenderFrameHostImpl* rfh =
      static_cast<RenderFrameHostImpl*>(execution_target.render_frame_host());
  if (!rfh->IsRenderFrameLive()) {
    return EvalJsResult(
        base::Value(), "Error: EvalJs won't work on an already-crashed frame.");
  }

  bool user_gesture = rfh->GetLifecycleState() !=
                          RenderFrameHost::LifecycleState::kPrerendering &&
                      !(options & EXECUTE_SCRIPT_NO_USER_GESTURE) &&
                      world_id == ISOLATED_WORLD_ID_GLOBAL;
  bool resolve_promises = !(options & EXECUTE_SCRIPT_NO_RESOLVE_PROMISES);
  bool honor_js_content_settings =
      options & EXECUTE_SCRIPT_HONOR_JS_CONTENT_SETTINGS;

  ExecuteJavaScriptForTestsWaiter waiter(rfh);
  rfh->ExecuteJavaScriptForTests(base::UTF8ToUTF16(script), user_gesture,
                                 resolve_promises, honor_js_content_settings,
                                 world_id, waiter.GetCallback());

  std::move(after_script_invoke).Run();

  bool has_value = waiter.Wait();
  if (!has_value) {
    return EvalJsResult(base::Value(),
                        "Timeout waiting for Javascript to execute.");
  }

  using blink::mojom::JavaScriptExecutionResultType;
  JavaScriptExecutionResultType result_type = waiter.GetResultType();
  const base::Value& result_value = waiter.GetResult();

  if (result_type == JavaScriptExecutionResultType::kException) {
    // Parse the stack trace here, and interleave lines of source code from
    // |script| to aid debugging.
    CHECK(result_value.is_string() && !result_value.GetString().empty());
    std::string error_text =
        "a JavaScript error: \"" + result_value.GetString() + "\"";
    return EvalJsResult(base::Value(),
                        AnnotateAndAdjustJsStackTraces(
                            error_text, std::string(source_url), script, 0));
  }

  return EvalJsResult(result_value.Clone(), std::string());
}

class ScopedTestDevToolsProtocolClient : public TestDevToolsProtocolClient {
 public:
  explicit ScopedTestDevToolsProtocolClient(RenderFrameHost& rfh) {
    AttachToFrameTreeHost(&rfh);
  }
  ~ScopedTestDevToolsProtocolClient() override { DetachProtocolClient(); }
};

}  // namespace

::testing::AssertionResult ExecJs(const ToRenderFrameHost& execution_target,
                                  std::string_view script,
                                  int options,
                                  int32_t world_id) {
  // TODO(nick): Do we care enough about folks shooting themselves in the foot
  // here with e.g. ASSERT_TRUE(ExecJs("window == window.top")) -- when they
  // mean EvalJs -- to fail a CHECK() when eval_result.value.is_bool()?
  EvalJsResult eval_result =
      EvalJs(execution_target, script, options, world_id);

  // NOTE: |eval_result.value| is intentionally ignored by ExecJs().
  if (!eval_result.is_ok()) {
    return ::testing::AssertionFailure() << eval_result;
  }
  return ::testing::AssertionSuccess();
}

EvalJsResult EvalJs(const ToRenderFrameHost& execution_target,
                    std::string_view script,
                    int options,
                    int32_t world_id,
                    base::OnceClosure after_script_invoke) {
  TRACE_EVENT1("test", "EvalJs", "script", script);

  // The sourceURL= parameter provides a string that replaces <anonymous> in
  // stack traces, if an Error is thrown. 'std::string' is meant to communicate
  // that this is a dynamic argument originating from C++ code.
  //
  // Wrapping the script in braces makes it run in a block scope so that
  // let/const don't leak outside the code being run, but vars will float to
  // the outer scope.
  const char* kSourceURL = "__const_std::string&_script__";
  std::string modified_script =
      base::StrCat({"{", script, "\n}\n//# sourceURL=", kSourceURL});

  return EvalJsRunner(execution_target, modified_script, kSourceURL, options,
                      world_id, std::move(after_script_invoke));
}

EvalJsResult EvalJsAfterLifecycleUpdate(
    const ToRenderFrameHost& execution_target,
    std::string_view raf_script,
    std::string_view script,
    int options,
    int32_t world_id) {
  TRACE_EVENT2("test", "EvalJsAfterLifecycleUpdate", "raf_script", raf_script,
               "script", script);

  const char* kSourceURL = "__const_std::string&_script__";
  const char* kWrapperURL = "__const_std::string&_EvalJsAfterLifecycleUpdate__";
  std::string modified_raf_script;
  if (raf_script.length()) {
    modified_raf_script =
        base::StrCat({raf_script, ";\n//# sourceURL=", kSourceURL});
  }
  std::string modified_script =
      base::StrCat({script, ";\n//# sourceURL=", kSourceURL});

  // This runner_script delays running the argument scripts until just before
  // (|raf_script|) and after (|script|) a rendering update.
  std::string runner_script = JsReplace(
      R"(new Promise((resolve, reject) => {
           requestAnimationFrame(() => {
             try { window.eval($1); } catch (e) { reject(e); }
             setTimeout(() => {
               try { resolve(window.eval($2)); } catch (e) { reject(e); }
             });
           });
         })
         //# sourceURL=$3)",
      modified_raf_script, modified_script, kWrapperURL);

  EvalJsResult result = EvalJsRunner(execution_target, runner_script,
                                     kWrapperURL, options, world_id);

  if (!result.is_ok() &&
      base::StartsWith(result.ExtractError(),
                       "a JavaScript error: \"EvalError: Evaluating",
                       base::CompareCase::SENSITIVE)) {
    return EvalJsResult(base::Value(),
                        base::StrCat({"EvalJsAfterLifecycleUpdate encountered "
                                      "an EvalError, because eval() "
                                      "is blocked by the document's CSP on "
                                      "this page. To test content that "
                                      "is protected by CSP, consider using "
                                      "EvalJsAfterLifecycleUpdate in an "
                                      "isolated world. Details: ",
                                      result.ExtractError()}));
  }
  return result;
}

RenderFrameHost* FrameMatchingPredicateOrNullptr(
    Page& page,
    base::RepeatingCallback<bool(RenderFrameHost*)> predicate) {
  std::set<RenderFrameHost*> frame_set;
  page.GetMainDocument().ForEachRenderFrameHost(
      [&predicate, &frame_set](RenderFrameHost* rfh) {
        if (predicate.Run(rfh)) {
          frame_set.insert(rfh);
        }
      });
  EXPECT_LE(frame_set.size(), 1u);
  return frame_set.size() == 1 ? *frame_set.begin() : nullptr;
}

RenderFrameHost* FrameMatchingPredicate(
    Page& page,
    base::RepeatingCallback<bool(RenderFrameHost*)> predicate) {
  RenderFrameHost* rfh =
      FrameMatchingPredicateOrNullptr(page, std::move(predicate));
  EXPECT_TRUE(rfh);
  return rfh;
}

bool FrameMatchesName(std::string_view name, RenderFrameHost* frame) {
  return frame->GetFrameName() == name;
}

bool FrameIsChildOfMainFrame(RenderFrameHost* frame) {
  return frame->GetParent() && !frame->GetParent()->GetParent();
}

bool FrameHasSourceUrl(const GURL& url, RenderFrameHost* frame) {
  return frame->GetLastCommittedURL() == url;
}

RenderFrameHost* ChildFrameAt(const ToRenderFrameHost& adapter, size_t index) {
  RenderFrameHostImpl* rfh =
      static_cast<RenderFrameHostImpl*>(adapter.render_frame_host());
  if (index >= rfh->frame_tree_node()->child_count()) {
    return nullptr;
  }
  return rfh->frame_tree_node()->child_at(index)->current_frame_host();
}

bool HasOriginKeyedProcess(RenderFrameHost* frame) {
  return static_cast<RenderFrameHostImpl*>(frame)
      ->GetSiteInstance()
      ->GetSiteInfo()
      .agent_cluster_key()
      .IsOriginKeyed();
}

bool HasSandboxedSiteInstance(RenderFrameHost* frame) {
  return static_cast<RenderFrameHostImpl*>(frame)
      ->GetSiteInstance()
      ->GetSiteInfo()
      .is_sandboxed();
}

std::vector<RenderFrameHost*> CollectAllRenderFrameHosts(
    RenderFrameHost* starting_rfh) {
  std::vector<RenderFrameHost*> visited_frames;
  starting_rfh->ForEachRenderFrameHost(
      [&](RenderFrameHost* rfh) { visited_frames.push_back(rfh); });
  return visited_frames;
}

std::vector<RenderFrameHost*> CollectAllRenderFrameHosts(Page& page) {
  return CollectAllRenderFrameHosts(&page.GetMainDocument());
}

std::vector<RenderFrameHost*> CollectAllRenderFrameHosts(
    WebContents* web_contents) {
  std::vector<RenderFrameHost*> visited_frames;
  web_contents->ForEachRenderFrameHost(
      [&](RenderFrameHost* rfh) { visited_frames.push_back(rfh); });
  return visited_frames;
}

std::vector<WebContents*> GetAllWebContents() {
  std::vector<WebContentsImpl*> all_wci = WebContentsImpl::GetAllWebContents();
  std::vector<WebContents*> all_wc;
  std::ranges::transform(all_wci, std::back_inserter(all_wc),
                         [](WebContentsImpl* wc) { return wc; });

  return all_wc;
}

#if BUILDFLAG(IS_CHROMEOS)
bool ExecuteWebUIResourceTest(WebContents* web_contents) {
  // Inject WebUI test runner script.
  std::string script;
  scoped_refptr<base::RefCountedMemory> bytes =
      ui::ResourceBundle::GetSharedInstance().LoadDataResourceBytes(
          IDR_ASH_WEBUI_COMMON_WEBUI_RESOURCE_TEST_JS);

  if (net::GZipHeader::HasGZipHeader(base::span(*bytes))) {
    AppendGzippedResource(*bytes, &script);
  } else {
    auto chars = base::as_chars(base::span(*bytes));
    script.append(chars.data(), chars.size());
  }

  script.append("\n");
  ExecuteScriptAsync(web_contents, script);

  DOMMessageQueue message_queue(web_contents);

  bool should_wait_flag = base::CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kWaitForDebuggerWebUI);

  if (should_wait_flag) {
    ExecuteScriptAsync(
        web_contents,
        "window.waitUser = true; "
        "window.go = function() { window.waitUser = false }; "
        "console.log('Waiting for debugger...'); "
        "console.log('Run: go() in the JS console when you are ready.');");
  }

  ExecuteScriptAsync(web_contents, "runTests()");

  std::string message;
  do {
    if (!message_queue.WaitForMessage(&message)) {
      return false;
    }
  } while (message.compare("\"PENDING\"") == 0);

  return message.compare("\"SUCCESS\"") == 0;
}
#endif  // BUILDFLAG(IS_CHROMEOS)

std::string GetCookies(BrowserContext* browser_context,
                       const GURL& url,
                       net::CookieOptions::SameSiteCookieContext context,
                       net::CookiePartitionKeyCollection key_collection) {
  mojo::Remote<network::mojom::CookieManager> cookie_manager;
  browser_context->GetDefaultStoragePartition()
      ->GetNetworkContext()
      ->GetCookieManager(cookie_manager.BindNewPipeAndPassReceiver());
  net::CookieOptions options;
  options.set_same_site_cookie_context(context);
  base::test::TestFuture<const net::CookieAccessResultList&,
                         const net::CookieAccessResultList&>
      future;
  cookie_manager->GetCookieList(url, options, key_collection,
                                future.GetCallback());
  return net::CanonicalCookie::BuildCookieLine(std::get<0>(future.Get()));
}

std::vector<net::CanonicalCookie> GetCanonicalCookies(
    BrowserContext* browser_context,
    const GURL& url,
    net::CookiePartitionKeyCollection key_collection) {
  mojo::Remote<network::mojom::CookieManager> cookie_manager;
  browser_context->GetDefaultStoragePartition()
      ->GetNetworkContext()
      ->GetCookieManager(cookie_manager.BindNewPipeAndPassReceiver());
  // Allow access to SameSite cookies in tests.
  net::CookieOptions options;
  options.set_same_site_cookie_context(
      net::CookieOptions::SameSiteCookieContext::MakeInclusive());
  base::test::TestFuture<const net::CookieAccessResultList&,
                         const net::CookieAccessResultList&>
      future;
  cookie_manager->GetCookieList(url, options, key_collection,
                                future.GetCallback());
  return net::cookie_util::StripAccessResults(std::get<0>(future.Get()));
}

bool SetCookie(
    BrowserContext* browser_context,
    const GURL& url,
    const std::string& value,
    net::CookieOptions::SameSiteCookieContext context,
    base::optional_ref<const net::CookiePartitionKey> cookie_partition_key) {
  if (cookie_partition_key) {
    DCHECK(base::Contains(base::ToLowerASCII(value), ";partitioned"));
  }
  mojo::Remote<network::mojom::CookieManager> cookie_manager;
  browser_context->GetDefaultStoragePartition()
      ->GetNetworkContext()
      ->GetCookieManager(cookie_manager.BindNewPipeAndPassReceiver());
  std::unique_ptr<net::CanonicalCookie> cc(
      net::CanonicalCookie::CreateForTesting(
          url, value, base::Time::Now(), std::nullopt /* server_time */,
          cookie_partition_key.CopyAsOptional()));
  DCHECK(cc.get());

  net::CookieOptions options;
  options.set_include_httponly();
  options.set_same_site_cookie_context(context);
  base::test::TestFuture<net::CookieAccessResult> future;
  cookie_manager->SetCanonicalCookie(*cc.get(), url, options,
                                     future.GetCallback());
  return future.Get().status.IsInclude();
}

uint32_t DeleteCookies(BrowserContext* browser_context,
                       network::mojom::CookieDeletionFilter filter) {
  mojo::Remote<network::mojom::CookieManager> cookie_manager;
  browser_context->GetDefaultStoragePartition()
      ->GetNetworkContext()
      ->GetCookieManager(cookie_manager.BindNewPipeAndPassReceiver());

  base::test::TestFuture<uint32_t> future;
  cookie_manager->DeleteCookies(
      network::mojom::CookieDeletionFilter::New(filter), future.GetCallback());
  return future.Get();
}

void FetchHistogramsFromChildProcesses() {
  // Wait for all initialized processes to be ready before fetching histograms
  // for the first time.
  for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
       !it.IsAtEnd(); it.Advance()) {
    RenderProcessHost* process = it.GetCurrentValue();
    if (process->IsInitializedAndNotDead() && !process->IsReady()) {
      RenderProcessHostWatcher ready_watcher(
          process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_READY);
      ready_watcher.Wait();
    }
  }

  base::RunLoop run_loop;

  FetchHistogramsAsynchronously(
      base::SingleThreadTaskRunner::GetCurrentDefault(), run_loop.QuitClosure(),
      // If this call times out, it means that a child process is not
      // responding, which is something we should not ignore.  The timeout is
      // set to be longer than the normal browser test timeout so that it will
      // be prempted by the normal timeout.
      TestTimeouts::action_max_timeout());
  run_loop.Run();
}

void SetupCrossSiteRedirector(net::EmbeddedTestServer* embedded_test_server) {
  embedded_test_server->RegisterRequestHandler(base::BindRepeating(
      &CrossSiteRedirectResponseHandler, embedded_test_server));
}

void SetFileSystemAccessPermissionContext(
    BrowserContext* browser_context,
    FileSystemAccessPermissionContext* permission_context) {
  static_cast<FileSystemAccessManagerImpl*>(
      browser_context->GetDefaultStoragePartition()
          ->GetFileSystemAccessEntryFactory())
      ->SetPermissionContextForTesting(permission_context);
}

bool WaitForRenderFrameReady(RenderFrameHost* rfh) {
  if (!rfh) {
    return false;
  }
  std::string result =
      EvalJs(rfh,
             "(async function() {"
             "  if (document.readyState != 'complete') {"
             "    await new Promise((resolve) =>"
             "      document.addEventListener('readystatechange', event => {"
             "        if (document.readyState == 'complete') {"
             "          resolve();"
             "        }"
             "      }));"
             "  }"
             "})().then(() => 'pageLoadComplete');",
             EXECUTE_SCRIPT_NO_USER_GESTURE)
          .ExtractString();
  EXPECT_EQ("pageLoadComplete", result);
  return "pageLoadComplete" == result;
}

void WaitForAccessibilityFocusChange() {
  base::RunLoop run_loop;
  ui::BrowserAccessibilityManager::SetFocusChangeCallbackForTesting(
      run_loop.QuitClosure());
  run_loop.Run();
}

ui::AXNodeData GetFocusedAccessibilityNodeInfo(WebContents* web_contents) {
  WebContentsImpl* web_contents_impl =
      static_cast<WebContentsImpl*>(web_contents);
  ui::BrowserAccessibilityManager* manager =
      web_contents_impl->GetRootBrowserAccessibilityManager();
  if (!manager) {
    return ui::AXNodeData();
  }
  ui::BrowserAccessibility* focused_node = manager->GetFocus();
  return focused_node->GetData();
}

bool AccessibilityTreeContainsNodeWithName(ui::BrowserAccessibility* node,
                                           std::string_view name) {
  // If an image annotation is set, it plays the same role as a name, so it
  // makes sense to check both in the same test helper.
  if (node->GetStringAttribute(ax::mojom::StringAttribute::kName) == name ||
      node->GetStringAttribute(ax::mojom::StringAttribute::kImageAnnotation) ==
          name) {
    return true;
  }
  for (unsigned i = 0; i < node->PlatformChildCount(); i++) {
    if (AccessibilityTreeContainsNodeWithName(node->PlatformGetChild(i),
                                              name)) {
      return true;
    }
  }
  return false;
}

void WaitForAccessibilityTreeToChange(WebContents* web_contents) {
  AccessibilityNotificationWaiter accessibility_waiter(web_contents);
  ASSERT_TRUE(accessibility_waiter.WaitForNotification());
}

bool WaitForAccessibilityTreeToChange(WebContents* web_contents,
                                      base::TimeDelta timeout) {
  AccessibilityNotificationWaiter accessibility_waiter(web_contents);
  return accessibility_waiter.WaitForNotificationWithTimeout(timeout);
}

void WaitForAccessibilityTreeToContainNodeWithName(WebContents* web_contents,
                                                   std::string_view name) {
  WebContentsImpl* web_contents_impl =
      static_cast<WebContentsImpl*>(web_contents);
  RenderFrameHostImpl* main_frame = static_cast<RenderFrameHostImpl*>(
      web_contents_impl->GetPrimaryMainFrame());
  ui::BrowserAccessibilityManager* main_frame_manager =
      main_frame->browser_accessibility_manager();
  while (!main_frame_manager ||
         !AccessibilityTreeContainsNodeWithName(
             main_frame_manager->GetBrowserAccessibilityRoot(), name)) {
    WaitForAccessibilityTreeToChange(web_contents);
    main_frame_manager = main_frame->browser_accessibility_manager();
  }
}

ui::AXTreeUpdate GetAccessibilityTreeSnapshot(WebContents* web_contents) {
  WebContentsImpl* web_contents_impl =
      static_cast<WebContentsImpl*>(web_contents);
  ui::BrowserAccessibilityManager* manager =
      web_contents_impl->GetRootBrowserAccessibilityManager();
  if (!manager) {
    return ui::AXTreeUpdate();
  }
  return manager->SnapshotAXTreeForTesting();
}

ui::AXTreeUpdate GetAccessibilityTreeSnapshotFromId(
    const ui::AXTreeID& tree_id) {
  ui::BrowserAccessibilityManager* manager =
      ui::BrowserAccessibilityManager::FromID(tree_id);
  return manager ? manager->SnapshotAXTreeForTesting() : ui::AXTreeUpdate();
}

ui::AXPlatformNodeDelegate* GetRootAccessibilityNode(
    WebContents* web_contents) {
  WebContentsImpl* web_contents_impl =
      static_cast<WebContentsImpl*>(web_contents);
  ui::BrowserAccessibilityManager* manager =
      web_contents_impl->GetRootBrowserAccessibilityManager();
  return manager ? manager->GetBrowserAccessibilityRoot() : nullptr;
}

FindAccessibilityNodeCriteria::FindAccessibilityNodeCriteria() = default;

FindAccessibilityNodeCriteria::~FindAccessibilityNodeCriteria() = default;

ui::AXPlatformNodeDelegate* FindAccessibilityNode(
    WebContents* web_contents,
    const FindAccessibilityNodeCriteria& criteria) {
  ui::AXPlatformNodeDelegate* root = GetRootAccessibilityNode(web_contents);
  CHECK(root);
  return FindAccessibilityNodeInSubtree(root, criteria);
}

ui::AXPlatformNodeDelegate* FindAccessibilityNodeInSubtree(
    ui::AXPlatformNodeDelegate* node,
    const FindAccessibilityNodeCriteria& criteria) {
  auto* node_internal =
      ui::BrowserAccessibility::FromAXPlatformNodeDelegate(node);
  DCHECK(node_internal);
  if ((!criteria.name ||
       node_internal->GetStringAttribute(ax::mojom::StringAttribute::kName) ==
           criteria.name.value()) &&
      (!criteria.role || node_internal->GetRole() == criteria.role.value())) {
    return node;
  }

  for (unsigned int i = 0; i < node_internal->PlatformChildCount(); ++i) {
    ui::BrowserAccessibility* child = node_internal->PlatformGetChild(i);
    ui::AXPlatformNodeDelegate* result =
        FindAccessibilityNodeInSubtree(child, criteria);
    if (result) {
      return result;
    }
  }
  return nullptr;
}

#if BUILDFLAG(IS_WIN)
template <typename T>
Microsoft::WRL::ComPtr<T> QueryInterfaceFromNode(
    ui::AXPlatformNodeDelegate* node) {
  Microsoft::WRL::ComPtr<T> result;
  EXPECT_HRESULT_SUCCEEDED(
      node->GetNativeViewAccessible()->QueryInterface(__uuidof(T), &result));
  return result;
}

void UiaGetPropertyValueVtArrayVtUnknownValidate(
    PROPERTYID property_id,
    ui::AXPlatformNodeDelegate* target_node,
    const std::vector<std::string>& expected_names) {
  ASSERT_TRUE(target_node);

  base::win::ScopedVariant result_variant;
  Microsoft::WRL::ComPtr<IRawElementProviderSimple> node_provider =
      QueryInterfaceFromNode<IRawElementProviderSimple>(target_node);

  node_provider->GetPropertyValue(property_id, result_variant.Receive());
  ASSERT_EQ(VT_ARRAY | VT_UNKNOWN, result_variant.type());
  ASSERT_EQ(1u, SafeArrayGetDim(V_ARRAY(result_variant.ptr())));

  LONG lower_bound, upper_bound, size;
  ASSERT_HRESULT_SUCCEEDED(
      SafeArrayGetLBound(V_ARRAY(result_variant.ptr()), 1, &lower_bound));
  ASSERT_HRESULT_SUCCEEDED(
      SafeArrayGetUBound(V_ARRAY(result_variant.ptr()), 1, &upper_bound));
  size = upper_bound - lower_bound + 1;
  ASSERT_EQ(static_cast<LONG>(expected_names.size()), size);

  std::vector<std::string> names;
  for (LONG i = 0; i < size; ++i) {
    Microsoft::WRL::ComPtr<IUnknown> unknown_element;
    ASSERT_HRESULT_SUCCEEDED(
        SafeArrayGetElement(V_ARRAY(result_variant.ptr()), &i,
                            static_cast<void**>(&unknown_element)));
    ASSERT_NE(nullptr, unknown_element);

    Microsoft::WRL::ComPtr<IRawElementProviderSimple>
        raw_element_provider_simple;
    ASSERT_HRESULT_SUCCEEDED(unknown_element.As(&raw_element_provider_simple));
    ASSERT_NE(nullptr, raw_element_provider_simple);

    base::win::ScopedVariant name;
    ASSERT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPropertyValue(
        UIA_NamePropertyId, name.Receive()));
    ASSERT_EQ(VT_BSTR, name.type());
    names.push_back(base::WideToUTF8(
        std::wstring(V_BSTR(name.ptr()), SysStringLen(V_BSTR(name.ptr())))));
  }

  ASSERT_THAT(names, ::testing::UnorderedElementsAreArray(expected_names));
}
#endif

RenderWidgetHost* GetKeyboardLockWidget(WebContents* web_contents) {
  return static_cast<WebContentsImpl*>(web_contents)->GetKeyboardLockWidget();
}

RenderWidgetHost* GetMouseLockWidget(WebContents* web_contents) {
  return static_cast<WebContentsImpl*>(web_contents)
      ->mouse_lock_widget_for_testing();
}

void RequestKeyboardLock(
    WebContents* web_contents,
    std::optional<base::flat_set<ui::DomCode>> codes,
    base::OnceCallback<void(blink::mojom::KeyboardLockRequestResult)>
        callback) {
  DCHECK(!codes.has_value() || !codes.value().empty());
  WebContentsImpl* web_contents_impl =
      static_cast<WebContentsImpl*>(web_contents);
  RenderWidgetHostImpl* render_widget_host_impl =
      web_contents_impl->GetPrimaryMainFrame()->GetRenderWidgetHost();
  render_widget_host_impl->Focus();
  render_widget_host_impl->RequestKeyboardLock(std::move(codes),
                                               std::move(callback));
}

void CancelKeyboardLock(WebContents* web_contents) {
  WebContentsImpl* web_contents_impl =
      static_cast<WebContentsImpl*>(web_contents);
  RenderWidgetHostImpl* render_widget_host_impl =
      web_contents_impl->GetPrimaryMainFrame()->GetRenderWidgetHost();
  render_widget_host_impl->CancelKeyboardLock();
}

ScreenOrientationDelegate* GetScreenOrientationDelegate() {
  return ScreenOrientationProvider::GetDelegateForTesting();
}

std::vector<RenderWidgetHostView*> GetInputEventRouterRenderWidgetHostViews(
    WebContents* web_contents) {
  return static_cast<WebContentsImpl*>(web_contents)
      ->GetRenderWidgetHostViewsForTests();
}

RenderWidgetHost* GetFocusedRenderWidgetHost(WebContents* web_contents) {
  WebContentsImpl* web_contents_impl =
      static_cast<WebContentsImpl*>(web_contents);
  return web_contents_impl->GetFocusedRenderWidgetHost(
      web_contents_impl->GetPrimaryMainFrame()->GetRenderWidgetHost());
}

bool IsRenderWidgetHostFocused(const RenderWidgetHost* host) {
  return static_cast<const RenderWidgetHostImpl*>(host)->is_focused();
}

WebContents* GetFocusedWebContents(WebContents* web_contents) {
  WebContentsImpl* web_contents_impl =
      static_cast<WebContentsImpl*>(web_contents);
  return web_contents_impl->GetFocusedWebContents();
}

namespace {

RenderFrameMetadataProviderImpl* RenderFrameMetadataProviderFromRenderFrameHost(
    RenderFrameHost* render_frame_host) {
  DCHECK(render_frame_host);
  DCHECK(render_frame_host->GetRenderWidgetHost());
  // This helper should return a valid provider since it's used for
  // RenderFrameSubmissionObserver ctor.
  DCHECK(RenderWidgetHostImpl::From(render_frame_host->GetRenderWidgetHost())
             ->render_frame_metadata_provider());
  return RenderWidgetHostImpl::From(render_frame_host->GetRenderWidgetHost())
      ->render_frame_metadata_provider();
}

}  // namespace

TitleWatcher::TitleWatcher(WebContents* web_contents,
                           std::u16string_view expected_title,
                           bool include_nestable_tasks)
    : WebContentsObserver(web_contents),
      run_loop_(include_nestable_tasks
                    ? base::RunLoop::Type::kNestableTasksAllowed
                    : base::RunLoop::Type::kDefault) {
  expected_titles_.emplace_back(expected_title);
}

void TitleWatcher::AlsoWaitForTitle(std::u16string_view expected_title) {
  expected_titles_.emplace_back(expected_title);
}

TitleWatcher::~TitleWatcher() = default;

const std::u16string& TitleWatcher::WaitAndGetTitle() {
  TestTitle();
  run_loop_.Run();
  return observed_title_;
}

void TitleWatcher::DidStopLoading() {
  // When navigating through the history, the restored NavigationEntry's title
  // will be used. If the entry ends up having the same title after we return
  // to it, as will usually be the case, then WebContentsObserver::TitleSet
  // will then be suppressed, since the NavigationEntry's title hasn't changed.
  TestTitle();
}

void TitleWatcher::TitleWasSet(NavigationEntry* entry) {
  TestTitle();
}

void TitleWatcher::TestTitle() {
  const std::u16string& current_title = web_contents()->GetTitle();
  if (base::Contains(expected_titles_, current_title)) {
    observed_title_ = current_title;
    run_loop_.Quit();
  }
}

RenderProcessHostWatcher::RenderProcessHostWatcher(
    RenderProcessHost* render_process_host,
    WatchType type)
    : type_(type),
      did_exit_normally_(true),
      allow_renderer_crashes_(
          std::make_unique<ScopedAllowRendererCrashes>(render_process_host)),
      quit_closure_(run_loop_.QuitClosure()) {
  observation_.Observe(render_process_host);
}

RenderProcessHostWatcher::RenderProcessHostWatcher(WebContents* web_contents,
                                                   WatchType type)
    : RenderProcessHostWatcher(
          web_contents->GetPrimaryMainFrame()->GetProcess(),
          type) {}
RenderProcessHostWatcher::~RenderProcessHostWatcher() = default;

void RenderProcessHostWatcher::Wait() {
  run_loop_.Run();

  DCHECK(allow_renderer_crashes_)
      << "RenderProcessHostWatcher::Wait() may only be called once";
  allow_renderer_crashes_.reset();
  // Call this here just in case something else quits the RunLoop.
  observation_.Reset();
}

void RenderProcessHostWatcher::QuitRunLoop() {
  std::move(quit_closure_).Run();
  observation_.Reset();
}

void RenderProcessHostWatcher::RenderProcessReady(RenderProcessHost* host) {
  if (type_ == WATCH_FOR_PROCESS_READY) {
    QuitRunLoop();
  }
}

void RenderProcessHostWatcher::RenderProcessExited(
    RenderProcessHost* host,
    const ChildProcessTerminationInfo& info) {
  did_exit_normally_ =
      info.status == base::TERMINATION_STATUS_NORMAL_TERMINATION;
  if (type_ == WATCH_FOR_PROCESS_EXIT) {
    QuitRunLoop();
  }
}

void RenderProcessHostWatcher::RenderProcessHostDestroyed(
    RenderProcessHost* host) {
  if (type_ == WATCH_FOR_HOST_DESTRUCTION) {
    QuitRunLoop();
  }
}

RenderProcessHostKillWaiter::RenderProcessHostKillWaiter(
    RenderProcessHost* render_process_host,
    std::string_view uma_name)
    : exit_watcher_(render_process_host,
                    RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT),
      uma_name_(uma_name) {}

std::optional<int> RenderProcessHostKillWaiter::Wait() {
  std::optional<bad_message::BadMessageReason> result;

  // Wait for the renderer kill.
  exit_watcher_.Wait();
#if !BUILDFLAG(IS_ANDROID)
  // Getting termination status on android is not reliable. To avoid flakiness,
  // we can skip this check and just check bad message. On other platforms we
  // want to verify that the renderer got killed, rather than exiting normally.
  if (exit_watcher_.did_exit_normally()) {
    LOG(ERROR) << "Renderer unexpectedly exited normally.";
    return result;
  }
#endif

  // Find the logged UMA data (if present).
  std::vector<base::Bucket> uma_samples =
      histogram_tester_.GetAllSamples(uma_name_);
  // No UMA will be present if the kill was not triggered by the //content layer
  // (e.g. if it was triggered by bad_message::ReceivedBadMessage from //chrome
  // layer or from somewhere in the //components layer).
  if (uma_samples.empty()) {
    LOG(ERROR) << "Unexpectedly found no '" << uma_name_ << "' samples.";
    return result;
  }
  const base::Bucket& bucket = uma_samples.back();
  // Assuming that user of RenderProcessHostKillWatcher makes sure that only one
  // kill can happen while using the class.
  DCHECK_EQ(1u, uma_samples.size())
      << "Multiple renderer kills are unsupported";

  return bucket.min;
}

RenderProcessHostBadMojoMessageWaiter::RenderProcessHostBadMojoMessageWaiter(
    RenderProcessHost* render_process_host)
    : monitored_render_process_id_(render_process_host->GetID()),
      kill_waiter_(render_process_host,
                   "Stability.BadMessageTerminated.Content") {
  // base::Unretained is safe below, because the destructor unregisters the
  // callback.
  RenderProcessHostImpl::SetBadMojoMessageCallbackForTesting(
      base::BindRepeating(
          &RenderProcessHostBadMojoMessageWaiter::OnBadMojoMessage,
          base::Unretained(this)));
}

RenderProcessHostBadMojoMessageWaiter::
    ~RenderProcessHostBadMojoMessageWaiter() {
  RenderProcessHostImpl::SetBadMojoMessageCallbackForTesting(
      RenderProcessHostImpl::BadMojoMessageCallbackForTesting());
}

std::optional<std::string> RenderProcessHostBadMojoMessageWaiter::Wait() {
  std::optional<int> bad_message_reason = kill_waiter_.Wait();
  if (!bad_message_reason.has_value()) {
    return std::nullopt;
  }
  if (bad_message_reason.value() != bad_message::RPH_MOJO_PROCESS_ERROR) {
    LOG(ERROR) << "Unexpected |bad_message_reason|: "
               << bad_message_reason.value();
    return std::nullopt;
  }

  return observed_mojo_error_;
}

void RenderProcessHostBadMojoMessageWaiter::OnBadMojoMessage(
    ChildProcessId render_process_id,
    const std::string& error) {
  if (render_process_id == monitored_render_process_id_) {
    observed_mojo_error_ = error;
  }
}

class DOMMessageQueue::MessageObserver : public WebContentsObserver {
 public:
  MessageObserver(DOMMessageQueue* queue, WebContents* contents)
      : WebContentsObserver(contents),
        queue_(queue),
        render_frame_host_(nullptr),
        watching_frame_(false) {}

  MessageObserver(DOMMessageQueue* queue, RenderFrameHost* render_frame_host)
      : WebContentsObserver(
            WebContents::FromRenderFrameHost(render_frame_host)),
        queue_(queue),
        render_frame_host_(render_frame_host),
        watching_frame_(true) {}

  ~MessageObserver() override = default;

 private:
  void DomOperationResponse(RenderFrameHost* rfh,
                            const std::string& result) override {
    if (!watching_frame_ || render_frame_host_ == rfh) {
      queue_->OnDomMessageReceived(result);
    }
  }

  void PrimaryMainFrameRenderProcessGone(
      base::TerminationStatus status) override {
    queue_->PrimaryMainFrameRenderProcessGone(status);
  }

  void RenderFrameDeleted(RenderFrameHost* render_frame_host) override {
    if (render_frame_host_ != render_frame_host) {
      return;
    }
    render_frame_host_ = nullptr;
    queue_->RenderFrameDeleted();
  }

  void WebContentsDestroyed() override {
    queue_->OnBackingWebContentsDestroyed(this);
  }

  raw_ptr<DOMMessageQueue> queue_;
  raw_ptr<RenderFrameHost> render_frame_host_;
  bool watching_frame_;
};

DOMMessageQueue::DOMMessageQueue() {
  // TODO(crbug.com/40746969): Remove the need to listen for this
  // notification.
  for (auto* contents : WebContentsImpl::GetAllWebContents()) {
    observers_.emplace(std::make_unique<MessageObserver>(this, contents));
  }
  web_contents_creation_subscription_ =
      RegisterWebContentsCreationCallback(base::BindRepeating(
          &DOMMessageQueue::OnWebContentsCreated, base::Unretained(this)));
}

DOMMessageQueue::DOMMessageQueue(WebContents* web_contents) {
  observers_.emplace(std::make_unique<MessageObserver>(this, web_contents));
}

DOMMessageQueue::DOMMessageQueue(RenderFrameHost* render_frame_host) {
  observers_.emplace(
      std::make_unique<MessageObserver>(this, render_frame_host));
}

DOMMessageQueue::~DOMMessageQueue() = default;

void DOMMessageQueue::PrimaryMainFrameRenderProcessGone(
    base::TerminationStatus status) {
  switch (status) {
    case base::TERMINATION_STATUS_NORMAL_TERMINATION:
    case base::TERMINATION_STATUS_STILL_RUNNING:
      break;
    default:
      renderer_crashed_ = true;
      if (callback_) {
        std::move(callback_).Run();
      }
      break;
  }
}

void DOMMessageQueue::RenderFrameDeleted() {
  if (callback_) {
    std::move(callback_).Run();
  }
}

void DOMMessageQueue::ClearQueue() {
  message_queue_ = base::queue<std::string>();
}

void DOMMessageQueue::OnDomMessageReceived(const std::string& message) {
  message_queue_.push(message);
  if (callback_) {
    std::move(callback_).Run();
  }
}

void DOMMessageQueue::OnWebContentsCreated(WebContents* contents) {
  observers_.emplace(std::make_unique<MessageObserver>(this, contents));
}

void DOMMessageQueue::OnBackingWebContentsDestroyed(MessageObserver* observer) {
  for (auto& entry : observers_) {
    if (entry.get() == observer) {
      observers_.erase(entry);
      break;
    }
  }
}

void DOMMessageQueue::SetOnMessageAvailableCallback(
    base::OnceClosure callback) {
  CHECK(!callback_);
  if (!message_queue_.empty() || renderer_crashed_) {
    std::move(callback).Run();
  } else {
    callback_ = std::move(callback);
  }
}

bool DOMMessageQueue::WaitForMessage(std::string* message) {
  DCHECK(message);
  if (!renderer_crashed_ && message_queue_.empty()) {
    // This will be quit when a new message comes in.
    base::RunLoop run_loop{base::RunLoop::Type::kNestableTasksAllowed};
    callback_ = run_loop.QuitClosure();
    run_loop.Run();
  }
  return PopMessage(message);
}

bool DOMMessageQueue::PopMessage(std::string* message) {
  DCHECK(message);
  if (renderer_crashed_ || message_queue_.empty()) {
    return false;
  }
  *message = message_queue_.front();
  message_queue_.pop();
  return true;
}

bool DOMMessageQueue::HasMessages() {
  return !message_queue_.empty();
}

WebContentsAddedObserver::WebContentsAddedObserver()
    : creation_subscription_(RegisterWebContentsCreationCallback(
          base::BindRepeating(&WebContentsAddedObserver::WebContentsCreated,
                              base::Unretained(this)))) {}

WebContentsAddedObserver::~WebContentsAddedObserver() = default;

void WebContentsAddedObserver::WebContentsCreated(WebContents* web_contents) {
  DCHECK(!web_contents_);
  web_contents_ = web_contents;

  if (quit_closure_) {
    std::move(quit_closure_).Run();
  }
}

WebContents* WebContentsAddedObserver::GetWebContents() {
  if (web_contents_) {
    return web_contents_;
  }

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

bool RequestFrame(WebContents* web_contents) {
  DCHECK(web_contents);
  return RenderWidgetHostImpl::From(web_contents->GetPrimaryMainFrame()
                                        ->GetRenderViewHost()
                                        ->GetWidget())
      ->RequestRepaintOnNewSurface();
}

RenderFrameSubmissionObserver::RenderFrameSubmissionObserver(
    RenderFrameMetadataProviderImpl* render_frame_metadata_provider)
    : render_frame_metadata_provider_(
          render_frame_metadata_provider->GetWeakPtr()) {
  render_frame_metadata_provider_->AddObserver(this);
  render_frame_metadata_provider_->ReportAllFrameSubmissionsForTesting(true);
}

RenderFrameSubmissionObserver::RenderFrameSubmissionObserver(
    FrameTreeNode* node)
    : RenderFrameSubmissionObserver(
          RenderFrameMetadataProviderFromRenderFrameHost(
              node->current_frame_host())) {}

RenderFrameSubmissionObserver::RenderFrameSubmissionObserver(
    WebContents* web_contents)
    : RenderFrameSubmissionObserver(
          RenderFrameMetadataProviderFromRenderFrameHost(
              web_contents->GetPrimaryMainFrame())) {}

RenderFrameSubmissionObserver::RenderFrameSubmissionObserver(
    RenderFrameHost* rfh)
    : RenderFrameSubmissionObserver(
          RenderFrameMetadataProviderFromRenderFrameHost(rfh)) {}

RenderFrameSubmissionObserver::~RenderFrameSubmissionObserver() {
  if (render_frame_metadata_provider_) {
    render_frame_metadata_provider_->RemoveObserver(this);
    render_frame_metadata_provider_->ReportAllFrameSubmissionsForTesting(false);
  }
}

void RenderFrameSubmissionObserver::WaitForAnyFrameSubmission() {
  break_on_any_frame_ = true;
  Wait();
  break_on_any_frame_ = false;
}

void RenderFrameSubmissionObserver::WaitForMetadataChange() {
  Wait();
}

void RenderFrameSubmissionObserver::WaitForPageScaleFactor(
    float expected_page_scale_factor,
    const float tolerance) {
  while (std::abs(render_frame_metadata_provider_->LastRenderFrameMetadata()
                      .page_scale_factor -
                  expected_page_scale_factor) > tolerance) {
    WaitForMetadataChange();
  }
}

void RenderFrameSubmissionObserver::WaitForExternalPageScaleFactor(
    float expected_external_page_scale_factor,
    const float tolerance) {
  while (std::abs(render_frame_metadata_provider_->LastRenderFrameMetadata()
                      .external_page_scale_factor -
                  expected_external_page_scale_factor) > tolerance) {
    WaitForMetadataChange();
  }
}

void RenderFrameSubmissionObserver::WaitForScrollOffset(
    const gfx::PointF& expected_offset) {
  while (render_frame_metadata_provider_->LastRenderFrameMetadata()
             .root_scroll_offset != expected_offset) {
    const auto& offset =
        render_frame_metadata_provider_->LastRenderFrameMetadata()
            .root_scroll_offset;
    constexpr float kEpsilon = 0.01f;
    if (offset.has_value()) {
      const auto diff = expected_offset - *offset;
      if (std::abs(diff.x()) <= kEpsilon && std::abs(diff.y()) <= kEpsilon) {
        break;
      }
    }
    WaitForMetadataChange();
  }
}

void RenderFrameSubmissionObserver::WaitForScrollOffsetAtTop(
    bool expected_scroll_offset_at_top) {
  while (render_frame_metadata_provider_->LastRenderFrameMetadata()
             .is_scroll_offset_at_top != expected_scroll_offset_at_top) {
    WaitForMetadataChange();
  }
}

const cc::RenderFrameMetadata&
RenderFrameSubmissionObserver::LastRenderFrameMetadata() const {
  return render_frame_metadata_provider_->LastRenderFrameMetadata();
}

void RenderFrameSubmissionObserver::NotifyOnNextMetadataChange(
    base::OnceClosure closure) {
  DCHECK(closure);
  DCHECK(metadata_change_closure_.is_null());
  metadata_change_closure_ = std::move(closure);
}

void RenderFrameSubmissionObserver::Quit() {
  if (quit_closure_) {
    std::move(quit_closure_).Run();
  }
}

void RenderFrameSubmissionObserver::Wait() {
  base::RunLoop run_loop{base::RunLoop::Type::kNestableTasksAllowed};
  quit_closure_ = run_loop.QuitClosure();
  run_loop.Run();
}

void RenderFrameSubmissionObserver::
    OnRenderFrameMetadataChangedBeforeActivation(
        const cc::RenderFrameMetadata& metadata) {}

void RenderFrameSubmissionObserver::OnRenderFrameMetadataChangedAfterActivation(
    base::TimeTicks activation_time) {
  Quit();
  if (metadata_change_closure_) {
    std::move(metadata_change_closure_).Run();
  }
}

void RenderFrameSubmissionObserver::OnRenderFrameSubmission() {
  render_frame_count_++;
  if (break_on_any_frame_) {
    Quit();
  }
}

void RenderFrameSubmissionObserver::OnLocalSurfaceIdChanged(
    const cc::RenderFrameMetadata& metadata) {}

MainThreadFrameObserver::MainThreadFrameObserver(
    RenderWidgetHost* render_widget_host)
    : render_widget_host_(render_widget_host),
      routing_id_(render_widget_host_->GetProcess()->GetNextRoutingID()) {}

MainThreadFrameObserver::~MainThreadFrameObserver() = default;

void MainThreadFrameObserver::Wait() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  static_cast<RenderWidgetHostImpl*>(render_widget_host_)
      ->InsertVisualStateCallback(base::BindOnce(&MainThreadFrameObserver::Quit,
                                                 base::Unretained(this)));
  base::RunLoop run_loop;
  quit_closure_ = run_loop.QuitClosure();
  run_loop.Run();
}

void MainThreadFrameObserver::Quit(bool) {
  if (quit_closure_) {
    std::move(quit_closure_).Run();
  }
}

InputMsgWatcher::InputMsgWatcher(RenderWidgetHost* render_widget_host,
                                 blink::WebInputEvent::Type type)
    : render_widget_host_(render_widget_host),
      wait_for_type_(type),
      ack_result_(blink::mojom::InputEventResultState::kUnknown),
      ack_source_(blink::mojom::InputEventResultSource::kUnknown) {
  render_widget_host->AddInputEventObserver(this);
}

InputMsgWatcher::~InputMsgWatcher() {
  render_widget_host_->RemoveInputEventObserver(this);
}

void InputMsgWatcher::OnInputEventAck(
    const RenderWidgetHost& widget,
    blink::mojom::InputEventResultSource ack_source,
    blink::mojom::InputEventResultState ack_state,
    const blink::WebInputEvent& event) {
  if (event.GetType() == wait_for_type_) {
    ack_result_ = ack_state;
    ack_source_ = ack_source;
    if (quit_closure_) {
      std::move(quit_closure_).Run();
    }
  }
}

void InputMsgWatcher::OnInputEvent(const RenderWidgetHost& widget,
                                   const blink::WebInputEvent& event) {
  last_sent_event_type_ = event.GetType();
}

bool InputMsgWatcher::HasReceivedAck() const {
  return ack_result_ != blink::mojom::InputEventResultState::kUnknown;
}

blink::mojom::InputEventResultState InputMsgWatcher::WaitForAck() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  base::RunLoop run_loop;
  quit_closure_ = run_loop.QuitClosure();
  run_loop.Run();
  return ack_result_;
}

blink::mojom::InputEventResultState
InputMsgWatcher::GetAckStateWaitIfNecessary() {
  if (HasReceivedAck()) {
    return ack_result_;
  }
  return WaitForAck();
}

InputEventAckWaiter::InputEventAckWaiter(RenderWidgetHost* render_widget_host,
                                         InputEventAckPredicate predicate)
    : render_widget_host_(
          static_cast<RenderWidgetHostImpl*>(render_widget_host)->GetWeakPtr()),
      predicate_(predicate) {
  render_widget_host_->AddInputEventObserver(this);
}

namespace {
InputEventAckWaiter::InputEventAckPredicate EventAckHasType(
    blink::WebInputEvent::Type type) {
  return base::BindRepeating(
      [](blink::WebInputEvent::Type expected_type,
         blink::mojom::InputEventResultSource source,
         blink::mojom::InputEventResultState state,
         const blink::WebInputEvent& event) {
        return event.GetType() == expected_type;
      },
      type);
}
}  // namespace

InputEventAckWaiter::InputEventAckWaiter(RenderWidgetHost* render_widget_host,
                                         blink::WebInputEvent::Type type)
    : InputEventAckWaiter(render_widget_host, EventAckHasType(type)) {}

InputEventAckWaiter::~InputEventAckWaiter() {
  if (render_widget_host_) {
    render_widget_host_->RemoveInputEventObserver(this);
  }
}

void InputEventAckWaiter::Wait() {
  if (!event_received_) {
    base::RunLoop run_loop;
    quit_closure_ = run_loop.QuitClosure();
    run_loop.Run();
  }
}

void InputEventAckWaiter::Reset() {
  event_received_ = false;
  quit_closure_ = base::OnceClosure();
}

void InputEventAckWaiter::OnInputEventAck(
    const RenderWidgetHost& widget,
    blink::mojom::InputEventResultSource source,
    blink::mojom::InputEventResultState state,
    const blink::WebInputEvent& event) {
  if (predicate_.Run(source, state, event)) {
    event_received_ = true;
    if (quit_closure_) {
      std::move(quit_closure_).Run();
    }
  }
}

// TODO(dcheng): Make the test clipboard on different threads share the
// same backing store. crbug.com/629765
// TODO(slangley): crbug.com/775830 - Cleanup BrowserTestClipboardScope now that
// there is no need to thread hop for Windows.
BrowserTestClipboardScope::BrowserTestClipboardScope() {
  ui::TestClipboard::CreateForCurrentThread();
}

BrowserTestClipboardScope::~BrowserTestClipboardScope() {
  ui::Clipboard::DestroyClipboardForCurrentThread();
}

void BrowserTestClipboardScope::SetRtf(const std::string& rtf) {
  ui::ScopedClipboardWriter clipboard_writer(ui::ClipboardBuffer::kCopyPaste);
  clipboard_writer.WriteRTF(rtf);
}

void BrowserTestClipboardScope::SetText(const std::string& text) {
  ui::ScopedClipboardWriter clipboard_writer(ui::ClipboardBuffer::kCopyPaste);
  clipboard_writer.WriteText(base::ASCIIToUTF16(text));
}

void BrowserTestClipboardScope::GetText(std::string* result) {
  ui::Clipboard::GetForCurrentThread()->ReadAsciiText(
      ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, result);
}

class FrameFocusedObserver::FrameTreeNodeObserverImpl
    : public FrameTreeNode::Observer {
 public:
  explicit FrameTreeNodeObserverImpl(FrameTreeNode* owner) : owner_(owner) {
    owner->AddObserver(this);
  }
  ~FrameTreeNodeObserverImpl() override {
    if (owner_) {
      owner_->RemoveObserver(this);
    }
  }

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

  void OnFrameTreeNodeFocused(FrameTreeNode* node) override {
    if (node == owner_) {
      run_loop_.Quit();
    }
  }

  void OnFrameTreeNodeDestroyed(FrameTreeNode* node) override {
    if (node == owner_) {
      owner_ = nullptr;
    }
  }

 private:
  raw_ptr<FrameTreeNode> owner_;
  base::RunLoop run_loop_;
};

FrameFocusedObserver::FrameFocusedObserver(RenderFrameHost* owner_host)
    : impl_(std::make_unique<FrameTreeNodeObserverImpl>(
          static_cast<RenderFrameHostImpl*>(owner_host)->frame_tree_node())) {}

FrameFocusedObserver::~FrameFocusedObserver() = default;

void FrameFocusedObserver::Wait() {
  impl_->Run();
}

class FrameDeletedObserver::FrameTreeNodeObserverImpl
    : public FrameTreeNode::Observer {
 public:
  explicit FrameTreeNodeObserverImpl(FrameTreeNode* owner)
      : frame_tree_node_id_(owner->frame_tree_node_id()), owner_(owner) {
    owner->AddObserver(this);
  }
  ~FrameTreeNodeObserverImpl() override = default;

  void Run() {
    if (!IsDestroyed()) {
      run_loop_.Run();
    }
  }

  bool IsDestroyed() const { return owner_ == nullptr; }

  FrameTreeNodeId frame_tree_node_id() const { return frame_tree_node_id_; }

 private:
  // FrameTreeNode::Observer:
  void OnFrameTreeNodeDestroyed(FrameTreeNode* node) override {
    if (node == owner_) {
      owner_ = nullptr;
      run_loop_.Quit();
    }
  }

  const FrameTreeNodeId frame_tree_node_id_;
  raw_ptr<FrameTreeNode> owner_;
  base::RunLoop run_loop_;
};

FrameDeletedObserver::FrameDeletedObserver(RenderFrameHost* owner_host)
    : impl_(std::make_unique<FrameTreeNodeObserverImpl>(
          static_cast<RenderFrameHostImpl*>(owner_host)->frame_tree_node())) {}

FrameDeletedObserver::~FrameDeletedObserver() = default;

void FrameDeletedObserver::Wait() {
  impl_->Run();
}

bool FrameDeletedObserver::IsDeleted() const {
  return impl_->IsDestroyed();
}

FrameTreeNodeId FrameDeletedObserver::GetFrameTreeNodeId() const {
  return impl_->frame_tree_node_id();
}

TestNavigationManager::TestNavigationManager(WebContents* web_contents,
                                             const GURL& url)
    : WebContentsObserver(web_contents), url_(url) {}

TestNavigationManager::~TestNavigationManager() {
  ResumeIfPaused();
}

bool TestNavigationManager::WaitForFirstYieldAfterDidStartNavigation() {
  TRACE_EVENT(
      "test",
      "TestNavigationManager::WaitForFirstYieldAfterDidStartNavigation");
  if (current_state_ >= NavigationState::WILL_START) {
    return true;
  }

  DCHECK_EQ(desired_state_, NavigationState::WILL_START);
  // Ignore the result because DidStartNavigation will update |desired_state_|
  // we check below.
  (void)WaitForDesiredState();
  // This returns false if the runloop was terminated by a timeout rather than
  // reaching the |WILL_START|.
  return current_state_ >= NavigationState::WILL_START;
}

bool TestNavigationManager::WaitForRequestStart() {
  TRACE_EVENT("test", "TestNavigationManager::WaitForRequestStart");
  desired_state_ = NavigationState::REQUEST_STARTED;
  return WaitForDesiredState();
}

bool TestNavigationManager::WaitForLoaderStart() {
  TRACE_EVENT("test", "TestNavigationManager::WaitForLoaderStart");
  desired_state_ = NavigationState::LOADER_STARTED;
  return WaitForDesiredState();
}

bool TestNavigationManager::WaitForRequestRedirected() {
  desired_state_ = NavigationState::REDIRECTED;
  return WaitForDesiredState();
}

void TestNavigationManager::ResumeNavigation() {
  TRACE_EVENT("test", "TestNavigationManager::ResumeNavigation");
  CHECK(current_state_ == NavigationState::REQUEST_STARTED ||
        current_state_ == NavigationState::REDIRECTED ||
        current_state_ == NavigationState::RESPONSE ||
        current_state_ == NavigationState::REQUEST_FAILED);
  CHECK_EQ(current_state_, desired_state_);
  CHECK(navigation_paused_);
  ResumeIfPaused();
}

NavigationHandle* TestNavigationManager::GetNavigationHandle() {
  return request_;
}

ukm::SourceId TestActivationManager::next_page_ukm_source_id() const {
  EXPECT_NE(ukm::kInvalidSourceId, next_page_ukm_source_id_);
  return next_page_ukm_source_id_;
}

bool TestNavigationManager::WaitForResponse() {
  TRACE_EVENT("test", "TestNavigationManager::WaitForResponse");
  desired_state_ = NavigationState::RESPONSE;
  return WaitForDesiredState();
}

bool TestNavigationManager::WaitForRequestFailed() {
  TRACE_EVENT("test", "TestNavigationManager::WaitForRequestFailed");
  desired_state_ = NavigationState::REQUEST_FAILED;
  return WaitForDesiredState();
}

bool TestNavigationManager::WaitForNavigationFinished() {
  TRACE_EVENT("test", "TestNavigationManager::WaitForNavigationFinished");
  desired_state_ = NavigationState::FINISHED;
  return WaitForDesiredState();
}

void TestNavigationManager::WaitForSpeculativeRenderFrameHostCreation() {
  TRACE_EVENT(
      "test",
      "TestNavigationManager::WaitForSpeculativeRenderFrameHostCreation");
  if (current_state_ < NavigationState::REQUEST_STARTED) {
    CHECK(WaitForRequestStart());
  }
  if (!speculative_rfh_created_) {
    base::RunLoop run_loop(message_loop_type_);
    wait_rfh_closure_ = run_loop.QuitClosure();
    ResumeNavigation();
    run_loop.Run();
  }
}

void TestNavigationManager::DidStartNavigation(NavigationHandle* handle) {
  if (!ShouldMonitorNavigation(handle)) {
    return;
  }

  DCHECK(!handle->IsPageActivation())
      << "For PageActivating navigations, use TestActivationManager.";

  request_ = NavigationRequest::From(handle);
  NavigationThrottleRegistry& registry =
      *request_->GetNavigationThrottleRegistryForTesting();
  registry.AddThrottle(std::make_unique<TestNavigationManagerThrottle>(
      registry,
      base::BindOnce(&TestNavigationManager::OnWillStartRequest,
                     weak_factory_.GetWeakPtr()),
      base::BindRepeating(&TestNavigationManager::OnWillRedirectRequest,
                          weak_factory_.GetWeakPtr()),
      base::BindOnce(&TestNavigationManager::OnWillProcessResponse,
                     weak_factory_.GetWeakPtr()),
      base::BindOnce(&TestNavigationManager::OnWillFailRequest,
                     weak_factory_.GetWeakPtr())));

  current_state_ = NavigationState::WILL_START;

  OnNavigationStateChanged();

  // This is the default desired state. A browser-initiated navigation can
  // reach WillStartRequest state synchronously, so the TestNavigationManager
  // is set to always pause navigations at WillStartRequest. This ensures the
  // navigation will defer and the user can always call
  // WaitForRequestStart.
  if (!request_->IsPageActivation() &&
      desired_state_ == NavigationState::WILL_START) {
    desired_state_ = NavigationState::REQUEST_STARTED;
  }
}

void TestNavigationManager::DidUpdateNavigationHandleTiming(
    NavigationHandle* handle) {
  if (handle != request_ ||
      handle->GetNavigationHandleTiming().loader_start_time.is_null() ||
      current_state_ >= NavigationState::LOADER_STARTED) {
    return;
  }

  CHECK(!handle->IsPageActivation())
      << "For PageActivating navigations, use TestActivationManager.";

  current_state_ = NavigationState::LOADER_STARTED;

  OnNavigationStateChanged();
}

void TestNavigationManager::DidRedirectNavigation(NavigationHandle* handle) {
  if (handle != request_) {
    return;
  }

  CHECK(!handle->IsPageActivation())
      << "For PageActivating navigations, use TestActivationManager.";

  current_state_ = NavigationState::REDIRECTED;

  OnNavigationStateChanged();
}

void TestNavigationManager::DidFinishNavigation(NavigationHandle* handle) {
  if (handle != request_) {
    return;
  }
  was_committed_ = handle->HasCommitted();
  was_successful_ = was_committed_ && !handle->IsErrorPage();
  current_state_ = NavigationState::FINISHED;
  navigation_paused_ = false;
  request_ = nullptr;

  // Invalidate the WeakPtrs so that the throttle callbacks will not be
  // called after this point. We need to do this because
  // TestNavigationManagerThrottle posts tasks for these callbacks and we
  // may get a call to this function before those tasks run.
  weak_factory_.InvalidateWeakPtrs();
  OnNavigationStateChanged();
}

void TestNavigationManager::OnWillStartRequest() {
  current_state_ = NavigationState::REQUEST_STARTED;
  navigation_paused_ = true;
  OnNavigationStateChanged();
}

void TestNavigationManager::OnWillRedirectRequest() {
  current_state_ = NavigationState::REDIRECTED;
  navigation_paused_ = true;
  OnNavigationStateChanged();
}

void TestNavigationManager::OnWillProcessResponse() {
  current_state_ = NavigationState::RESPONSE;
  navigation_paused_ = true;
  OnNavigationStateChanged();
}

void TestNavigationManager::OnWillFailRequest() {
  current_state_ = NavigationState::REQUEST_FAILED;
  navigation_paused_ = true;
  OnNavigationStateChanged();
}

void TestNavigationManager::RenderFrameCreated(
    RenderFrameHost* render_frame_host) {
  RenderFrameHostImpl* host_impl =
      static_cast<RenderFrameHostImpl*>(render_frame_host);
  NavigationRequest* request =
      host_impl->frame_tree_node()->navigation_request();
  if (host_impl->lifecycle_state() ==
          RenderFrameHostImpl::LifecycleStateImpl::kSpeculative &&
      IsRequestCompatibleWithSpeculativeRFH(request) &&
      request->GetURL() == url_ &&
      (request == request_ || request_ == nullptr)) {
    DCHECK(host_impl->frame_tree_node()->HasNavigation());
    speculative_rfh_created_ = true;
    created_speculative_rfh_ =
        std::make_unique<RenderFrameHostWrapper>(render_frame_host);
    if (wait_rfh_closure_) {
      std::move(wait_rfh_closure_).Run();
    }
  }
}

RenderFrameHost* TestNavigationManager::GetCreatedSpeculativeRFH() {
  if (!created_speculative_rfh_) {
    return nullptr;
  }
  return created_speculative_rfh_->get();
}

// TODO(csharrison): Remove CallResumeForTesting method calls in favor of doing
// it through the throttle.
bool TestNavigationManager::WaitForDesiredState() {
  // If the desired state has already been reached, just return.
  if (current_state_ == desired_state_) {
    return true;
  }

  // Resume the navigation if it was paused.
  ResumeIfPaused();

  // Wait for the desired state if needed.
  if (current_state_ < desired_state_) {
    DCHECK(!state_quit_closure_);
    base::RunLoop run_loop(message_loop_type_);
    state_quit_closure_ = run_loop.QuitClosure();
    run_loop.Run();
  }

  // Return false if the navigation did not reach the state specified by the
  // user.
  return current_state_ == desired_state_;
}

void TestNavigationManager::OnNavigationStateChanged() {
  TRACE_EVENT("test", "TestNavigationManager::OnNavigationStateChanged", "this",
              this);

  // If the state the user was waiting for has been reached, exit the message
  // loop.
  if (current_state_ >= desired_state_) {
    if (state_quit_closure_) {
      std::move(state_quit_closure_).Run();
    }
    return;
  }

  // Otherwise, the navigation should be resumed if it was previously paused.
  ResumeIfPaused();
}

void TestNavigationManager::ResumeIfPaused() {
  TRACE_EVENT("test", "TestNavigationManager::ResumeIfPaused", "this", this);

  if (!navigation_paused_) {
    return;
  }

  navigation_paused_ = false;

  auto* registry = request_->GetNavigationThrottleRegistryForTesting();
  ASSERT_EQ(1u, registry->GetDeferringThrottles().size());
  registry->ResumeProcessingNavigationEvent(
      *registry->GetDeferringThrottles().cbegin());
}

bool TestNavigationManager::ShouldMonitorNavigation(NavigationHandle* handle) {
  if (request_ || handle->GetURL() != url_) {
    return false;
  }
  if (current_state_ != NavigationState::INITIAL) {
    return false;
  }
  return true;
}

void TestNavigationManager::AllowNestableTasks() {
  message_loop_type_ = base::RunLoop::Type::kNestableTasksAllowed;
}

void TestNavigationManager::WriteIntoTrace(
    perfetto::TracedValue context) const {
  perfetto::TracedDictionary dict = std::move(context).WriteDictionary();
  dict.Add("url", url_);
  dict.Add("navigation_request", request_);
  dict.Add("navigation_paused", navigation_paused_);
  dict.Add("current_state", current_state_);
  dict.Add("desired_state", desired_state_);
}

namespace {

// A helper CommitDeferringCondition instantiated and inserted into all
// navigations from TestActivationManager. It delegates WillCommitNavigation
// method of the CommitDeferringCondition back to the TestActivationManager so
// that the manager can see and decide how to proceed with the condition for
// every occurring navigation.
class TestActivationManagerCondition : public CommitDeferringCondition {
  using WillCommitCallback =
      base::OnceCallback<Result(CommitDeferringCondition&, base::OnceClosure)>;

 public:
  TestActivationManagerCondition(NavigationHandle& handle,
                                 WillCommitCallback on_will_commit_navigation)
      : CommitDeferringCondition(handle),
        on_will_commit_navigation_(std::move(on_will_commit_navigation)) {}
  ~TestActivationManagerCondition() override = default;

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

  Result WillCommitNavigation(base::OnceClosure resume) override {
    return std::move(on_will_commit_navigation_).Run(*this, std::move(resume));
  }
  const char* TraceEventName() const override {
    return "TestActivationManagerCondition";
  }

 private:
  WillCommitCallback on_will_commit_navigation_;
};

// We need this wrapper since the TestActivationManager can be destroyed while
// navigations are ongoing so we need to pass the callback with a WeakPtr.
// However, we can't bind a WeakPtr to a method that returns non-void so we use
// this wrapper to provide the default return value.
CommitDeferringCondition::Result ConditionCallbackWeakWrapper(
    base::WeakPtr<TestActivationManager> manager,
    base::RepeatingCallback<
        CommitDeferringCondition::Result(TestActivationManager*,
                                         CommitDeferringCondition&,
                                         base::OnceClosure)> manager_func,
    CommitDeferringCondition& condition,
    base::OnceClosure resume_callback) {
  // If the manager was destroyed, we don't need to pause navigation any longer
  // so just proceed.
  if (!manager) {
    return CommitDeferringCondition::Result::kProceed;
  }

  return manager_func.Run(manager.get(), condition, std::move(resume_callback));
}

}  // namespace

class TestActivationManager::ConditionInserter {
  using WillCommitCallback =
      base::RepeatingCallback<CommitDeferringCondition::Result(
          CommitDeferringCondition&,
          base::OnceClosure)>;

 public:
  explicit ConditionInserter(WillCommitCallback callback,
                             CommitDeferringConditionRunner::InsertOrder order)
      : condition_callback_(std::move(callback)),
        generator_id_(
            CommitDeferringConditionRunner::InstallConditionGeneratorForTesting(
                base::BindRepeating(&ConditionInserter::Install,
                                    base::Unretained(this)),
                order)) {}
  ~ConditionInserter() {
    CommitDeferringConditionRunner::UninstallConditionGeneratorForTesting(
        generator_id_);
  }

 private:
  std::unique_ptr<CommitDeferringCondition> Install(
      NavigationHandle& handle,
      CommitDeferringCondition::NavigationType navigation_type) {
    // TestActivationManager should only pause during checks for an activating
    // navigation. It's possible for a navigation to start off as activating
    // but become non-activating after the initial checks. In that case,
    // CommitDeferringConditions will be run a second time as non-activating so
    // we'll avoid registering the second time with this early out.
    // TODO(bokan): We can't check navigation_type here because BFCache is
    // considered kOther. Ideally all page activations would be a single type.
    // crbug.com/1226442.
    auto* request = NavigationRequest::From(&handle);
    if (!request->IsServedFromBackForwardCache() &&
        !request->is_running_potential_prerender_activation_checks()) {
      return nullptr;
    }

    return std::make_unique<TestActivationManagerCondition>(
        handle, condition_callback_);
  }

  WillCommitCallback condition_callback_;
  const int generator_id_;
};

TestActivationManager::TestActivationManager(WebContents* web_contents,
                                             const GURL& url)
    : WebContentsObserver(web_contents), url_(url) {
  first_condition_inserter_ = std::make_unique<ConditionInserter>(
      base::BindRepeating(
          &ConditionCallbackWeakWrapper, weak_factory_.GetWeakPtr(),
          base::BindRepeating(&TestActivationManager::FirstConditionCallback)),
      CommitDeferringConditionRunner::InsertOrder::kBefore);
  last_condition_inserter_ = std::make_unique<ConditionInserter>(
      base::BindRepeating(
          &ConditionCallbackWeakWrapper, weak_factory_.GetWeakPtr(),
          base::BindRepeating(&TestActivationManager::LastConditionCallback)),
      CommitDeferringConditionRunner::InsertOrder::kAfter);
}

TestActivationManager::~TestActivationManager() {
  DCHECK(!quit_closure_);
  if (is_paused()) {
    std::move(resume_callback_).Run();
  }
}

bool TestActivationManager::WaitForBeforeChecks() {
  TRACE_EVENT("test", "TestActivationManager::WaitForBeforeChecks");
  desired_state_ = ActivationState::kBeforeChecks;
  return WaitForDesiredState();
}

bool TestActivationManager::WaitForAfterChecks() {
  TRACE_EVENT("test", "TestActivationManager::WaitForAfterChecks");
  desired_state_ = ActivationState::kAfterChecks;
  return WaitForDesiredState();
}

void TestActivationManager::WaitForNavigationFinished() {
  TRACE_EVENT("test", "TestActivationManager::WaitForNavigationFinished");
  desired_state_ = ActivationState::kFinished;
  bool finished = WaitForDesiredState();
  DCHECK(finished);
}

void TestActivationManager::ResumeActivation() {
  TRACE_EVENT("test", "TestActivationManager::ResumeActivation");
  DCHECK(is_paused());

  // Set desired_state_ to kFinished so the navigation can proceed to finish
  // unless it yields somewhere and/or the caller calls another WaitFor method.
  desired_state_ = ActivationState::kFinished;
  std::move(resume_callback_).Run();
}

NavigationHandle* TestActivationManager::GetNavigationHandle() {
  return request_;
}

void TestActivationManager::SetCallbackCalledAfterActivationIsReady(
    base::OnceClosure callback) {
  DCHECK(!callback_in_last_condition);
  callback_in_last_condition = std::move(callback);
}

CommitDeferringCondition::Result TestActivationManager::FirstConditionCallback(
    CommitDeferringCondition& condition,
    base::OnceClosure resume_callback) {
  if (condition.GetNavigationHandle().GetURL() != url_) {
    return CommitDeferringCondition::Result::kProceed;
  }

  DCHECK(!is_tracking_activation_)
      << "Second request for watched URL: " << url_;
  is_tracking_activation_ = true;

  DCHECK(!request_);
  request_ = NavigationRequest::From(&condition.GetNavigationHandle());
  DCHECK(request_->is_running_potential_prerender_activation_checks() ||
         request_->IsServedFromBackForwardCache())
      << "TestActivationManager should only be used for for page "
         "activations. For regular navigations, use TestNavigationManager.";

  DCHECK_EQ(current_state_, ActivationState::kInitial);
  current_state_ = ActivationState::kBeforeChecks;

  if (current_state_ < desired_state_) {
    return CommitDeferringCondition::Result::kProceed;
  }

  resume_callback_ = std::move(resume_callback);
  StopWaitingIfNeeded();

  // Always defer here so test code gets a chance to set WaitFor... before the
  // navigation finishes.
  return CommitDeferringCondition::Result::kDefer;
}

CommitDeferringCondition::Result TestActivationManager::LastConditionCallback(
    CommitDeferringCondition& condition,
    base::OnceClosure resume_callback) {
  if (callback_in_last_condition) {
    std::move(callback_in_last_condition).Run();
  }

  if (request_ != &condition.GetNavigationHandle()) {
    return CommitDeferringCondition::Result::kProceed;
  }

  DCHECK(is_tracking_activation_);

  current_state_ = ActivationState::kAfterChecks;
  if (current_state_ < desired_state_) {
    return CommitDeferringCondition::Result::kProceed;
  }

  resume_callback_ = std::move(resume_callback);
  StopWaitingIfNeeded();

  return CommitDeferringCondition::Result::kDefer;
}

void TestActivationManager::DidFinishNavigation(NavigationHandle* handle) {
  if (handle == request_) {
    DCHECK(is_tracking_activation_);
    was_committed_ = handle->HasCommitted();
    was_successful_ = was_committed_ && !handle->IsErrorPage();
    was_activated_ = was_successful_ && handle->IsPageActivation();
    next_page_ukm_source_id_ = handle->GetNextPageUkmSourceId();
    request_ = nullptr;
    current_state_ = ActivationState::kFinished;
    StopWaitingIfNeeded();
  }
}

bool TestActivationManager::WaitForDesiredState() {
  DCHECK_LE(current_state_, desired_state_);

  // If the desired state has already been reached, just return.
  if (current_state_ == desired_state_) {
    return true;
  }

  // Resume the navigation if it was paused.
  if (is_paused()) {
    ResumeActivation();
  }

  // Wait for the desired state if needed.
  if (current_state_ < desired_state_) {
    DCHECK(!quit_closure_);
    base::RunLoop run_loop(base::RunLoop::Type::kDefault);
    quit_closure_ = run_loop.QuitClosure();
    run_loop.Run();
  }

  // Return false if the navigation did not reach the state specified by the
  // user.
  return current_state_ == desired_state_;
}

void TestActivationManager::StopWaitingIfNeeded() {
  if (current_state_ == desired_state_ && quit_closure_) {
    std::move(quit_closure_).Run();
  }
}

NavigationHandleCommitObserver::NavigationHandleCommitObserver(
    WebContents* web_contents,
    const GURL& url)
    : WebContentsObserver(web_contents), url_(url) {}

void NavigationHandleCommitObserver::DidFinishNavigation(
    NavigationHandle* handle) {
  if (handle->GetURL() != url_) {
    return;
  }
  has_committed_ = true;
  was_same_document_ = handle->IsSameDocument();
  was_renderer_initiated_ = handle->IsRendererInitiated();
  navigation_type_ =
      NavigationRequest::From(handle)->common_params().navigation_type;
}

WebContentsConsoleObserver::WebContentsConsoleObserver(
    WebContents* web_contents)
    : WebContentsObserver(web_contents) {}
WebContentsConsoleObserver::~WebContentsConsoleObserver() = default;

bool WebContentsConsoleObserver::Wait() {
  return waiter_helper_.Wait();
}

void WebContentsConsoleObserver::SetFilter(Filter filter) {
  filter_ = std::move(filter);
}

void WebContentsConsoleObserver::SetPattern(std::string pattern) {
  DCHECK(!pattern.empty()) << "An empty pattern will never match.";
  pattern_ = std::move(pattern);
}

std::string WebContentsConsoleObserver::GetMessageAt(size_t index) const {
  if (index >= messages_.size()) {
    ADD_FAILURE() << "Tried to retrieve a non-existent message at index: "
                  << index;
    return std::string();
  }
  return base::UTF16ToUTF8(messages_[index].message);
}

void WebContentsConsoleObserver::OnDidAddMessageToConsole(
    RenderFrameHost* source_frame,
    blink::mojom::ConsoleMessageLevel log_level,
    const std::u16string& message_contents,
    int32_t line_no,
    const std::u16string& source_id,
    const std::optional<std::u16string>& untrusted_stack_trace) {
  Message message(
      {source_frame, log_level, message_contents, line_no, source_id});
  if (filter_ && !filter_.Run(message)) {
    return;
  }

  if (!pattern_.empty() &&
      !base::MatchPattern(base::UTF16ToUTF8(message_contents), pattern_)) {
    return;
  }

  messages_.push_back(std::move(message));
  waiter_helper_.OnEvent();
}

namespace {
static constexpr int kEnableLogMessageId = 0;
static constexpr char kEnableLogMessage[] = R"({"id":0,"method":"Log.enable"})";
static constexpr int kDisableLogMessageId = 1;
static constexpr char kDisableLogMessage[] =
    R"({"id":1,"method":"Log.disable"})";

static constexpr int kEnableMediaMessageId = 2;
static constexpr char kEnableMediaMessage[] =
    R"({"id":2,"method":"Media.enable"})";
static constexpr int kDisableMediaMessageId = 3;
static constexpr char kDisableMediaMessage[] =
    R"({"id":3,"method":"Media.disable"})";
}  // namespace

DevToolsInspectorLogWatcher::DevToolsInspectorLogWatcher(
    WebContents* web_contents,
    Domain domain) {
  host_ = DevToolsAgentHost::GetOrCreateFor(web_contents);
  host_->AttachClient(this);

  switch (domain) {
    case Domain::Log:
      host_->DispatchProtocolMessage(
          this, base::byte_span_from_cstring(kEnableLogMessage));
      break;
    case Domain::Media:
      host_->DispatchProtocolMessage(
          this, base::byte_span_from_cstring(kEnableMediaMessage));
      break;
    default:
      NOTREACHED();
  }

  run_loop_enable_log_.Run();
  domain_ = domain;
}

DevToolsInspectorLogWatcher::~DevToolsInspectorLogWatcher() {
  host_->DetachClient(this);
}

void DevToolsInspectorLogWatcher::DispatchProtocolMessage(
    DevToolsAgentHost* host,
    base::span<const uint8_t> message) {
  std::string_view message_str(reinterpret_cast<const char*>(message.data()),
                               message.size());
  auto parsed_message = std::move(
      base::JSONReader::Read(message_str, base::JSON_PARSE_CHROMIUM_EXTENSIONS)
          ->GetDict());
  std::optional<int> command_id = parsed_message.FindInt("id");
  if (command_id.has_value()) {
    switch (command_id.value()) {
      case kEnableLogMessageId:
      case kEnableMediaMessageId:
        run_loop_enable_log_.Quit();
        break;
      case kDisableLogMessageId:
      case kDisableMediaMessageId:
        run_loop_disable_log_.Quit();
        break;
      default:
        NOTREACHED();
    }
    return;
  }

  std::string* notification = parsed_message.FindString("method");
  if (!notification) {
    return;
  }

  if (*notification == "Log.entryAdded") {
    std::string* text =
        parsed_message.FindStringByDottedPath("params.entry.text");
    DCHECK(text);
    last_message_ = *text;
    std::string* url =
        parsed_message.FindStringByDottedPath("params.entry.url");
    if (url) {
      last_url_ = GURL(*url);
    }
  }

  if (notification->find("Media.") != std::string::npos) {
    last_media_notification_ = *notification;

    if (*notification == "Media.playerEventsAdded") {
      bool last_auto_pip_event_info_set = false;
      const base::Value::List* events =
          parsed_message.FindListByDottedPath("params.events");
      if (events) {
        for (const base::Value& event : *events) {
          const auto* dict = event.GetIfDict();
          if (!dict) {
            continue;
          }
          const std::string* text = dict->FindString("value");
          if ((text != nullptr) &&
              ((*text).find("auto_picture_in_picture_info") !=
               std::string::npos)) {
            last_auto_picture_in_picture_event_info_ = *text;
            last_auto_pip_event_info_set = true;
          }
        }
      }
      if (last_auto_pip_event_info_set) {
        NotifyLastAutoPipEventInfoSet();
      }
    }
  }
}

void DevToolsInspectorLogWatcher::AgentHostClosed(DevToolsAgentHost* host) {}

void DevToolsInspectorLogWatcher::FlushAndStopWatching() {
  switch (domain_) {
    case Domain::Log:
      host_->DispatchProtocolMessage(
          this, base::byte_span_from_cstring(kDisableLogMessage));
      break;
    case Domain::Media:
      host_->DispatchProtocolMessage(
          this, base::byte_span_from_cstring(kDisableMediaMessage));
      break;
    default:
      NOTREACHED();
  }

  run_loop_disable_log_.Run();
}

void DevToolsInspectorLogWatcher::NotifyLastAutoPipEventInfoSet() {
  for (DevToolsInspectorLogWatcherObserver& obs : observers_) {
    obs.OnLastAutoPipEventInfoSet();
  }
}

namespace {
mojo::Remote<blink::mojom::FileSystemManager> GetFileSystemManager(
    RenderProcessHost* rph,
    const blink::StorageKey& storage_key) {
  FileSystemManagerImpl* file_system = static_cast<RenderProcessHostImpl*>(rph)
                                           ->GetFileSystemManagerForTesting();
  mojo::Remote<blink::mojom::FileSystemManager> file_system_manager_remote;
  GetIOThreadTaskRunner({})->PostTask(
      FROM_HERE,
      base::BindOnce(&FileSystemManagerImpl::BindReceiver,
                     base::Unretained(file_system), storage_key,
                     file_system_manager_remote.BindNewPipeAndPassReceiver()));
  return file_system_manager_remote;
}
}  // namespace

// static
void PwnMessageHelper::FileSystemCreate(RenderProcessHost* process,
                                        int request_id,
                                        GURL path,
                                        bool exclusive,
                                        bool is_directory,
                                        bool recursive,
                                        const blink::StorageKey& storage_key) {
  TestFileapiOperationWaiter waiter;
  mojo::Remote<blink::mojom::FileSystemManager> file_system_manager =
      GetFileSystemManager(process, storage_key);
  file_system_manager->Create(
      path, exclusive, is_directory, recursive,
      base::BindOnce(&TestFileapiOperationWaiter::DidCreate,
                     base::Unretained(&waiter)));
  waiter.WaitForOperationToFinish();
}

// static
void PwnMessageHelper::FileSystemWrite(RenderProcessHost* process,
                                       int request_id,
                                       GURL file_path,
                                       std::string blob_uuid,
                                       int64_t position,
                                       const blink::StorageKey& storage_key) {
  TestFileapiOperationWaiter waiter;
  mojo::Remote<blink::mojom::FileSystemManager> file_system_manager =
      GetFileSystemManager(process, storage_key);
  mojo::PendingRemote<blink::mojom::FileSystemOperationListener> listener;
  mojo::Receiver<blink::mojom::FileSystemOperationListener> receiver(
      &waiter, listener.InitWithNewPipeAndPassReceiver());
  mojo::Remote<blink::mojom::FileSystemCancellableOperation> op;

  file_system_manager->Write(
      file_path, process->GetBrowserContext()->GetBlobRemote(blob_uuid),
      position, op.BindNewPipeAndPassReceiver(), std::move(listener));
  waiter.WaitForOperationToFinish();
}

void PwnMessageHelper::OpenURL(RenderFrameHost* render_frame_host,
                               const GURL& url) {
  auto params = blink::mojom::OpenURLParams::New();
  params->url = url;
  params->disposition = WindowOpenDisposition::CURRENT_TAB;
  params->should_replace_current_entry = false;
  params->user_gesture = true;
  static_cast<mojom::FrameHost*>(
      static_cast<RenderFrameHostImpl*>(render_frame_host))
      ->OpenURL(std::move(params));
}

#if defined(USE_AURA)
namespace {

// This class interacts with the internals of the DelegatedFrameHost without
// exposing them in the header.
class EvictionStateWaiter : public DelegatedFrameHost::Observer {
 public:
  explicit EvictionStateWaiter(DelegatedFrameHost* delegated_frame_host)
      : delegated_frame_host_(delegated_frame_host) {
    delegated_frame_host_->AddObserverForTesting(this);
  }

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

  ~EvictionStateWaiter() override {
    delegated_frame_host_->RemoveObserverForTesting(this);
  }

  void WaitForEvictionState(DelegatedFrameHost::FrameEvictionState state) {
    if (delegated_frame_host_->frame_eviction_state() == state) {
      return;
    }

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

  // DelegatedFrameHost::Observer:
  void OnFrameEvictionStateChanged(
      DelegatedFrameHost::FrameEvictionState new_state) override {
    if (!quit_closure_.is_null() && (new_state == waited_eviction_state_)) {
      std::move(quit_closure_).Run();
    }
  }

 private:
  raw_ptr<DelegatedFrameHost> delegated_frame_host_;
  DelegatedFrameHost::FrameEvictionState waited_eviction_state_;
  base::OnceClosure quit_closure_;
};

}  // namespace

void VerifyStaleContentOnFrameEviction(
    RenderWidgetHostView* render_widget_host_view) {
  auto* render_widget_host_view_aura =
      static_cast<RenderWidgetHostViewAura*>(render_widget_host_view);
  DelegatedFrameHost* delegated_frame_host =
      render_widget_host_view_aura->GetDelegatedFrameHost();

  // Initially there should be no stale content set.
  EXPECT_FALSE(
      delegated_frame_host->stale_content_layer()->has_external_content());
  EXPECT_EQ(delegated_frame_host->frame_eviction_state(),
            DelegatedFrameHost::FrameEvictionState::kNotStarted);

  // Hide the view and evict the frame, and expect that stale content will be
  // set.
  EvictionStateWaiter waiter{delegated_frame_host};
  render_widget_host_view_aura->WasOccluded();
  static_cast<viz::FrameEvictorClient*>(delegated_frame_host)
      ->EvictDelegatedFrame(delegated_frame_host->GetFrameEvictorForTesting()
                                ->CollectSurfaceIdsForEviction());
  EXPECT_EQ(delegated_frame_host->frame_eviction_state(),
            DelegatedFrameHost::FrameEvictionState::kPendingEvictionRequests);
  // Wait until the stale frame content is copied and set onto the layer, i.e.
  // the eviction state changes from kPendingEvictionRequests back to
  // kNotStarted.
  waiter.WaitForEvictionState(
      DelegatedFrameHost::FrameEvictionState::kNotStarted);
  EXPECT_TRUE(
      delegated_frame_host->stale_content_layer()->has_external_content());
}

#endif  // defined(USE_AURA)

// static
void BlobURLStoreInterceptor::Intercept(GURL target_url,
                                        storage::BlobUrlRegistry* registry,
                                        mojo::ReceiverId receiver_id) {
  auto interceptor = base::WrapUnique(new BlobURLStoreInterceptor(target_url));
  auto* raw_interceptor = interceptor.get();
  auto impl = registry->receivers_for_testing().SwapImplForTesting(
      receiver_id, std::move(interceptor));
  raw_interceptor->url_store_ = std::move(impl);
}

blink::mojom::BlobURLStore* BlobURLStoreInterceptor::GetForwardingInterface() {
  return url_store_.get();
}

void BlobURLStoreInterceptor::Register(
    mojo::PendingRemote<blink::mojom::Blob> blob,
    const GURL& url,
    RegisterCallback callback) {
  GetForwardingInterface()->Register(std::move(blob), target_url_,
                                     std::move(callback));
}

BlobURLStoreInterceptor::BlobURLStoreInterceptor(GURL target_url)
    : target_url_(target_url) {}
BlobURLStoreInterceptor::~BlobURLStoreInterceptor() = default;

namespace {

int LoadBasicRequest(
    network::mojom::URLLoaderFactory* url_loader_factory,
    const GURL& url,
    int load_flags,
    const std::optional<url::Origin>& request_initiator = std::nullopt) {
  auto request = std::make_unique<network::ResourceRequest>();
  request->url = url;
  request->load_flags = load_flags;
  request->request_initiator = request_initiator;
  // Allow access to SameSite cookies in tests.
  request->site_for_cookies = net::SiteForCookies::FromUrl(url);

  SimpleURLLoaderTestHelper simple_loader_helper;
  std::unique_ptr<network::SimpleURLLoader> simple_loader =
      network::SimpleURLLoader::Create(std::move(request),
                                       TRAFFIC_ANNOTATION_FOR_TESTS);

  simple_loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
      url_loader_factory, simple_loader_helper.GetCallbackDeprecated());
  simple_loader_helper.WaitForCallback();

  return simple_loader->NetError();
}

}  // namespace

int LoadBasicRequest(network::mojom::NetworkContext* network_context,
                     const GURL& url,
                     int load_flags) {
  mojo::Remote<network::mojom::URLLoaderFactory> url_loader_factory;
  network::mojom::URLLoaderFactoryParamsPtr url_loader_factory_params =
      network::mojom::URLLoaderFactoryParams::New();
  url_loader_factory_params->process_id = network::mojom::kBrowserProcessId;
  url_loader_factory_params->is_orb_enabled = false;
  url::Origin origin = url::Origin::Create(url);
  url_loader_factory_params->isolation_info =
      net::IsolationInfo::CreateForInternalRequest(origin);
  network_context->CreateURLLoaderFactory(
      url_loader_factory.BindNewPipeAndPassReceiver(),
      std::move(url_loader_factory_params));
  // |url_loader_factory| will receive disconnect notification asynchronously if
  // |network_context| is already disconnected. However it's still false
  // at this point.
  EXPECT_TRUE(url_loader_factory.is_connected());

  return LoadBasicRequest(url_loader_factory.get(), url, load_flags);
}

int LoadBasicRequest(RenderFrameHost* frame, const GURL& url) {
  mojo::Remote<network::mojom::URLLoaderFactory> url_loader_factory;
  frame->CreateNetworkServiceDefaultFactory(
      url_loader_factory.BindNewPipeAndPassReceiver());
  return LoadBasicRequest(
      url_loader_factory.get(), url, 0 /* load_flags */,
      frame->GetLastCommittedOrigin() /* request_initiator */);
}

void EnsureCookiesFlushed(BrowserContext* browser_context) {
  browser_context->ForEachLoadedStoragePartition(
      [](StoragePartition* partition) {
        base::RunLoop run_loop;
        partition->GetCookieManagerForBrowserProcess()->FlushCookieStore(
            run_loop.QuitClosure());
        run_loop.Run();
      });
}

bool TestGuestAutoresize(WebContents* embedder_web_contents,
                         RenderFrameHost* guest_main_frame) {
  RenderFrameProxyHost* subframe_proxy_host =
      FrameTreeNode::From(guest_main_frame)
          ->render_manager()
          ->GetProxyToOuterDelegate();
  RenderWidgetHostImpl* guest_rwh_impl = static_cast<RenderWidgetHostImpl*>(
      guest_main_frame->GetRenderWidgetHost());

  auto interceptor = std::make_unique<SynchronizeVisualPropertiesInterceptor>(
      subframe_proxy_host);

  viz::LocalSurfaceId current_id =
      guest_rwh_impl->GetView()->GetLocalSurfaceId();
  // The guest may not yet be fully attached / initted. If not, |current_id|
  // will be invalid, and we should wait for an ID before proceeding.
  if (!current_id.is_valid()) {
    current_id = interceptor->WaitForSurfaceId();
  }

  // Enable auto-resize.
  gfx::Size min_size(10, 10);
  gfx::Size max_size(100, 100);
  guest_rwh_impl->SetAutoResize(true, min_size, max_size);
  guest_rwh_impl->GetView()->EnableAutoResize(min_size, max_size);

  // Enabling auto resize generates a surface ID, wait for it.
  current_id = interceptor->WaitForSurfaceId();

  // Fake an auto-resize update.
  viz::LocalSurfaceId local_surface_id(current_id.parent_sequence_number(),
                                       current_id.child_sequence_number() + 1,
                                       current_id.embed_token());
  cc::RenderFrameMetadata metadata;
  metadata.viewport_size_in_pixels = gfx::Size(75, 75);
  metadata.local_surface_id = local_surface_id;
  guest_rwh_impl->OnLocalSurfaceIdChanged(metadata);

  // This won't generate a response, as we short-circuit auto-resizes, so cause
  // an additional update by disabling auto-resize.
  guest_rwh_impl->GetView()->DisableAutoResize(gfx::Size(75, 75));

  // Get the first delivered surface id and ensure it has the surface id which
  // we expect.
  return interceptor->WaitForSurfaceId() ==
         viz::LocalSurfaceId(current_id.parent_sequence_number() + 1,
                             current_id.child_sequence_number() + 1,
                             current_id.embed_token());
}

RenderWidgetHostMouseEventMonitor::RenderWidgetHostMouseEventMonitor(
    RenderWidgetHost* host)
    : host_(host), event_received_(false) {
  mouse_callback_ = base::BindRepeating(
      &RenderWidgetHostMouseEventMonitor::MouseEventCallback,
      base::Unretained(this));
  host_->AddMouseEventCallback(mouse_callback_);
}

RenderWidgetHostMouseEventMonitor::~RenderWidgetHostMouseEventMonitor() {
  host_->RemoveMouseEventCallback(mouse_callback_);
}

DidStartNavigationObserver::DidStartNavigationObserver(WebContents* contents)
    : WebContentsObserver(contents) {}
DidStartNavigationObserver::~DidStartNavigationObserver() = default;

void DidStartNavigationObserver::DidStartNavigation(NavigationHandle* handle) {
  if (observed_) {
    return;
  }
  observed_ = true;
  navigation_handle_ = handle;
  run_loop_.Quit();
}

void DidStartNavigationObserver::DidFinishNavigation(NavigationHandle* handle) {
  if (navigation_handle_ == handle) {
    navigation_handle_ = nullptr;
  }
}

ProxyDSFObserver::ProxyDSFObserver() {
  // Set callback and observer to track the creation of RenderFrameProxyHosts.
  ProxyHostObserver* observer = GetProxyHostObserver();
  observer->set_created_callback(base::BindRepeating(
      &ProxyDSFObserver::OnCreation, base::Unretained(this)));
  RenderFrameProxyHost::SetObserverForTesting(observer);
}

ProxyDSFObserver::~ProxyDSFObserver() {
  // Stop observing RenderFrameProxyHosts.
  GetProxyHostObserver()->Reset();
  RenderFrameProxyHost::SetObserverForTesting(nullptr);
}

void ProxyDSFObserver::WaitForOneProxyHostCreation() {
  if (!proxy_host_created_dsf_.empty()) {
    return;
  }
  runner_ = std::make_unique<base::RunLoop>();
  runner_->Run();
}

void ProxyDSFObserver::OnCreation(RenderFrameProxyHost* rfph) {
  // Not all RenderFrameProxyHosts will be created with a
  // CrossProcessFrameConnector. We're only interested in the ones that do.
  if (auto* cpfc = rfph->cross_process_frame_connector()) {
    proxy_host_created_dsf_.push_back(
        cpfc->screen_infos().current().device_scale_factor);
  }
  if (runner_) {
    runner_->Quit();
  }
}

bool CompareWebContentsOutputToReference(
    WebContents* web_contents,
    const base::FilePath& expected_path,
    const gfx::Size& snapshot_size,
    const cc::PixelComparator& comparator) {
  // Produce a frame of output first to ensure the system is in a consistent,
  // known state.
  {
    base::RunLoop run_loop;
    web_contents->GetPrimaryMainFrame()->InsertVisualStateCallback(
        base::BindLambdaForTesting([&](bool visual_state_updated) {
          ASSERT_TRUE(visual_state_updated);
          run_loop.Quit();
        }));
    run_loop.Run();
  }

  auto* rwh = RenderWidgetHostImpl::From(
      web_contents->GetPrimaryMainFrame()->GetRenderViewHost()->GetWidget());

  if (!rwh->GetView() || !rwh->GetView()->IsSurfaceAvailableForCopy()) {
    ADD_FAILURE() << "RWHV surface not available for copy.";
    return false;
  }

  bool snapshot_matches = false;
  {
    base::RunLoop run_loop;
    rwh->GetView()->CopyFromSurface(
        gfx::Rect(), gfx::Size(),
        base::BindLambdaForTesting([&](const viz::CopyOutputBitmapWithMetadata&
                                           result) {
          const SkBitmap& bitmap = result.bitmap;
          base::ScopedAllowBlockingForTesting allow_blocking;
          ASSERT_FALSE(bitmap.drawsNothing());

          SkBitmap clipped_bitmap;
          bitmap.extractSubset(
              &clipped_bitmap,
              SkIRect::MakeWH(snapshot_size.width(), snapshot_size.height()));

          snapshot_matches =
              cc::MatchesPNGFile(clipped_bitmap, expected_path, comparator);

          // When rebaselining the pixel test, the test may fail. However, the
          // reference file will still be overwritten.
          if (base::CommandLine::ForCurrentProcess()->HasSwitch(
                  switches::kRebaselinePixelTests)) {
            ASSERT_TRUE(cc::WritePNGFile(clipped_bitmap, expected_path,
                                         /*discard_transparency=*/false));
          }

          run_loop.Quit();
        }));
    run_loop.Run();
  }

  return snapshot_matches;
}

RenderFrameHostChangedCallbackRunner::RenderFrameHostChangedCallbackRunner(
    WebContents* content,
    RenderFrameHostChangedCallback callback)
    : WebContentsObserver(content), callback_(std::move(callback)) {}

RenderFrameHostChangedCallbackRunner::~RenderFrameHostChangedCallbackRunner() =
    default;

void RenderFrameHostChangedCallbackRunner::RenderFrameHostChanged(
    RenderFrameHost* old_host,
    RenderFrameHost* new_host) {
  if (callback_) {
    std::move(callback_).Run(old_host, new_host);
  }
}

DidFinishNavigationObserver::DidFinishNavigationObserver(
    WebContents* web_contents,
    base::RepeatingCallback<void(NavigationHandle*)> callback)
    : WebContentsObserver(web_contents), callback_(callback) {}

DidFinishNavigationObserver::DidFinishNavigationObserver(
    RenderFrameHost* render_frame_host,
    base::RepeatingCallback<void(NavigationHandle*)> callback)
    : DidFinishNavigationObserver(
          WebContents::FromRenderFrameHost(render_frame_host),
          callback) {}

DidFinishNavigationObserver::~DidFinishNavigationObserver() = default;

void DidFinishNavigationObserver::DidFinishNavigation(
    NavigationHandle* navigation_handle) {
  callback_.Run(navigation_handle);
}

// Since the loading state might be switched more than once due to navigation
// restart, the following helper methods for history traversal need to call
// `WaitForNavigationFinished()` to ensure the navigation is finally committed
// and `WaitForLoadStop()` to ensure the `WebContents` finishes the last
// loading.
bool HistoryGoToIndex(WebContents* wc, int index) {
  TestNavigationObserver observer(wc);
  wc->GetController().GoToIndex(index);
  WaitForNavigationFinished(wc, observer);
  return WaitForLoadStop(wc);
}

bool HistoryGoToOffset(WebContents* wc, int offset) {
  TestNavigationObserver observer(wc);
  wc->GetController().GoToOffset(offset);
  WaitForNavigationFinished(wc, observer);
  return WaitForLoadStop(wc);
}

bool HistoryGoBack(WebContents* wc) {
  TestNavigationObserver observer(wc);
  wc->GetController().GoBack();
  WaitForNavigationFinished(wc, observer);
  return WaitForLoadStop(wc);
}

bool HistoryGoForward(WebContents* wc) {
  TestNavigationObserver observer(wc);
  wc->GetController().GoForward();
  WaitForNavigationFinished(wc, observer);
  return WaitForLoadStop(wc);
}

CreateAndLoadWebContentsObserver::CreateAndLoadWebContentsObserver(
    int num_expected_contents)
    : creation_subscription_(
          RegisterWebContentsCreationCallback(base::BindRepeating(
              &CreateAndLoadWebContentsObserver::OnWebContentsCreated,
              base::Unretained(this)))),
      num_expected_contents_(num_expected_contents) {
  EXPECT_GE(num_expected_contents, 1);
}

CreateAndLoadWebContentsObserver::~CreateAndLoadWebContentsObserver() = default;

void CreateAndLoadWebContentsObserver::OnWebContentsCreated(
    WebContents* web_contents) {
  ++num_new_contents_seen_;
  if (num_new_contents_seen_ < num_expected_contents_) {
    return;
  }

  // If there is already a WebContents, then this will fail the test later.
  if (num_new_contents_seen_ > num_expected_contents_) {
    ADD_FAILURE() << "Unexpected WebContents creation";
    // If we're called before Wait(), then `contents_creation_quit_closure_`
    // has not been set. If we're called after, then we'll clear this when
    // we see the creation of the expected contents and it won't be set again.
    EXPECT_FALSE(contents_creation_quit_closure_);
    return;
  }

  web_contents_ = web_contents;
  load_stop_observer_.emplace(web_contents_);

  if (contents_creation_quit_closure_) {
    std::move(contents_creation_quit_closure_).Run();
  }
}

WebContents* CreateAndLoadWebContentsObserver::Wait() {
  // Wait for a new WebContents if we haven't gotten one yet.
  if (!load_stop_observer_) {
    base::RunLoop run_loop;
    contents_creation_quit_closure_ = run_loop.QuitClosure();
    run_loop.Run();
  }

  load_stop_observer_->Wait();

  // Do this after waiting for load to complete, since only the specified number
  // of WebContents should be created before Wait() returns. If an additional
  // one is created while the expected contents is loading, then we still fail
  // the test.
  EXPECT_EQ(num_expected_contents_, num_new_contents_seen_);
  creation_subscription_ = base::CallbackListSubscription();

  return web_contents_;
}

CookieChangeObserver::CookieChangeObserver(WebContents* web_contents,
                                           int num_expected_calls)
    : WebContentsObserver(web_contents),
      run_loop_(base::RunLoop::Type::kNestableTasksAllowed),
      num_expected_calls_(num_expected_calls) {}

CookieChangeObserver::~CookieChangeObserver() = default;

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

void CookieChangeObserver::OnCookiesAccessed(
    RenderFrameHost* render_frame_host,
    const CookieAccessDetails& details) {
  OnCookieAccessed(details);
}

void CookieChangeObserver::OnCookiesAccessed(
    NavigationHandle* navigation,
    const CookieAccessDetails& details) {
  OnCookieAccessed(details);
}

void CookieChangeObserver::OnCookieAccessed(
    const CookieAccessDetails& details) {
  if (details.type == CookieAccessDetails::Type::kRead) {
    num_read_seen_++;
  } else if (details.type == CookieAccessDetails::Type::kChange) {
    num_write_seen_++;
  }

  if (++num_seen_ == num_expected_calls_) {
    run_loop_.Quit();
  }
}

SpeculativeRenderFrameHostObserver::SpeculativeRenderFrameHostObserver(
    WebContents* web_contents,
    const GURL& url)
    : WebContentsObserver(web_contents), url_(url) {}

SpeculativeRenderFrameHostObserver::~SpeculativeRenderFrameHostObserver() =
    default;

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

void SpeculativeRenderFrameHostObserver::RenderFrameCreated(
    RenderFrameHost* render_frame_host) {
  RenderFrameHostImpl* host_impl =
      static_cast<RenderFrameHostImpl*>(render_frame_host);
  NavigationRequest* request =
      host_impl->frame_tree_node()->navigation_request();
  if (host_impl->lifecycle_state() ==
          RenderFrameHostImpl::LifecycleStateImpl::kSpeculative &&
      IsRequestCompatibleWithSpeculativeRFH(request) &&
      request->GetURL() == url_) {
    run_loop_.Quit();
  }
}

SpareRenderProcessHostStartedObserver::SpareRenderProcessHostStartedObserver() {
  scoped_observation_.Observe(&SpareRenderProcessHostManager::Get());
}

SpareRenderProcessHostStartedObserver::
    ~SpareRenderProcessHostStartedObserver() = default;

void SpareRenderProcessHostStartedObserver::OnSpareRenderProcessHostReady(
    RenderProcessHost* host) {
  spare_render_process_host_ = host;
  if (quit_closure_) {
    std::move(quit_closure_).Run();
  }
}

RenderProcessHost*
SpareRenderProcessHostStartedObserver::WaitForSpareRenderProcessStarted() {
  base::RunLoop loop;
  quit_closure_ = loop.QuitClosure();
  if (!spare_render_process_host_) {
    loop.Run();
  }

  RenderProcessHost* host = std::exchange(spare_render_process_host_, nullptr);
  scoped_observation_.Reset();
  return host;
}

base::CallbackListSubscription RegisterWebContentsCreationCallback(
    base::RepeatingCallback<void(WebContents*)> callback) {
  return WebContentsImpl::FriendWrapper::AddCreatedCallbackForTesting(callback);
}

#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
void SetConditionalFocusWindowForTesting(base::TimeDelta window) {
  MediaStreamManager::GetInstance()->SetConditionalFocusWindowForTesting(
      window);
}

void SetCapturedSurfaceControllerFactoryForTesting(
    base::RepeatingCallback<std::unique_ptr<MockCapturedSurfaceController>(
        GlobalRenderFrameHostId,
        WebContentsMediaCaptureId)> factory) {
  using FactoryType =
      ::base::RepeatingCallback<std::unique_ptr<CapturedSurfaceController>(
          GlobalRenderFrameHostId, WebContentsMediaCaptureId,
          base::RepeatingCallback<void(int)>)>;
  using MockFactoryType =
      ::base::RepeatingCallback<std::unique_ptr<MockCapturedSurfaceController>(
          GlobalRenderFrameHostId, WebContentsMediaCaptureId)>;

  FactoryType wrapped_factory = base::BindRepeating(
      [](MockFactoryType mock_factory, GlobalRenderFrameHostId rfh_id,
         WebContentsMediaCaptureId captured_wc_id,
         base::RepeatingCallback<void(int)> on_zoom_level_change_callback) {
        std::unique_ptr<MockCapturedSurfaceController> mock_controller =
            mock_factory.Run(rfh_id, captured_wc_id);
        std::unique_ptr<CapturedSurfaceController> wrapped_object =
            base::WrapUnique<CapturedSurfaceController>(
                mock_controller.release());
        return wrapped_object;
      },
      factory);

  MediaStreamManager::GetInstance()
      ->SetCapturedSurfaceControllerFactoryForTesting(wrapped_factory);
}
#endif  // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)

std::optional<int> GetDOMNodeId(RenderFrameHost& rfh,
                                std::string_view query_selector) {
  ScopedTestDevToolsProtocolClient devtools_client(rfh);

  // Get the document node.
  const base::Value::Dict* result =
      devtools_client.SendCommandSync("DOM.getDocument");
  CHECK(result);

  std::optional<int> document_id = result->FindIntByDottedPath("root.nodeId");
  CHECK(document_id.has_value());

  // Find a node matching the selector in the document.
  auto params = base::Value::Dict()
                    .Set("nodeId", document_id.value())
                    .Set("selector", query_selector);
  result =
      devtools_client.SendCommandSync("DOM.querySelector", std::move(params));
  CHECK(result);

  // QuerySelector returns a node_id: 0 when the selector isn't matched.
  std::optional<int> node_id = result->FindInt("nodeId");
  if (!node_id || node_id.value() == 0) {
    return std::nullopt;
  }

  // Extract the backendNodeId from the matched node. backendNodeId corresponds
  // to the Blink DOMNodeId
  params = base::Value::Dict().Set("nodeId", node_id.value());
  result =
      devtools_client.SendCommandSync("DOM.describeNode", std::move(params));
  CHECK(result);

  std::optional<int> dom_node_id =
      result->FindIntByDottedPath("node.backendNodeId");
  CHECK(dom_node_id.has_value());

  return dom_node_id;
}

std::optional<int> GetDOMNodeIdFromSubframe(
    content::RenderFrameHost& rfh,
    std::string_view subframe_query_selector,
    std::string_view query_selector) {
  content::ScopedTestDevToolsProtocolClient devtools_client(rfh);

  // Get the main document node.
  const base::Value::Dict* result =
      devtools_client.SendCommandSync("DOM.getDocument");
  CHECK(result);
  std::optional<int> document_id = result->FindIntByDottedPath("root.nodeId");
  CHECK(document_id.has_value());

  // Find the <iframe> element node in the main document.
  auto params = base::Value::Dict()
                    .Set("nodeId", document_id.value())
                    .Set("selector", subframe_query_selector);
  result =
      devtools_client.SendCommandSync("DOM.querySelector", std::move(params));
  CHECK(result);
  std::optional<int> iframe_node_id = result->FindInt("nodeId");
  if (!iframe_node_id || iframe_node_id.value() == 0) {
    return std::nullopt;
  }

  // Get contentDocument of iframe.
  params = base::Value::Dict().Set("nodeId", iframe_node_id.value());
  result =
      devtools_client.SendCommandSync("DOM.describeNode", std::move(params));
  CHECK(result);
  std::optional<int> content_doc_backend_node_id =
      result->FindIntByDottedPath("node.contentDocument.backendNodeId");
  if (!content_doc_backend_node_id) {
    return std::nullopt;
  }

  // Resolve that backendNodeId to get a Runtime objectId for the document.
  params = base::Value::Dict().Set("backendNodeId",
                                   content_doc_backend_node_id.value());
  result =
      devtools_client.SendCommandSync("DOM.resolveNode", std::move(params));
  CHECK(result);
  const std::string* content_doc_object_id =
      result->FindStringByDottedPath("object.objectId");
  if (!content_doc_object_id) {
    return std::nullopt;
  }

  // Request the DOM nodeId for the iframe's document from its objectId.
  params = base::Value::Dict().Set("objectId", *content_doc_object_id);
  result =
      devtools_client.SendCommandSync("DOM.requestNode", std::move(params));
  CHECK(result);
  std::optional<int> content_doc_node_id = result->FindInt("nodeId");
  if (!content_doc_node_id || content_doc_node_id.value() == 0) {
    return std::nullopt;
  }

  // Query for the target element within the iframe's document.
  params = base::Value::Dict()
               .Set("nodeId", content_doc_node_id.value())
               .Set("selector", query_selector);
  result =
      devtools_client.SendCommandSync("DOM.querySelector", std::move(params));
  CHECK(result);
  std::optional<int> final_node_id = result->FindInt("nodeId");
  if (!final_node_id || final_node_id.value() == 0) {
    return std::nullopt;
  }

  params = base::Value::Dict().Set("nodeId", final_node_id.value());
  result =
      devtools_client.SendCommandSync("DOM.describeNode", std::move(params));
  CHECK(result);
  std::optional<int> dom_node_id =
      result->FindIntByDottedPath("node.backendNodeId");
  CHECK(dom_node_id.has_value());

  return dom_node_id;
}

namespace {

class DOMContentLoadedObserver : public WebContentsObserver {
 public:
  explicit DOMContentLoadedObserver(RenderFrameHost* render_frame_host)
      : WebContentsObserver(
            WebContents::FromRenderFrameHost(render_frame_host)),
        render_frame_host_(render_frame_host->GetWeakDocumentPtr()) {}

  void DOMContentLoaded(RenderFrameHost* render_frame_host) override {
    if (render_frame_host_.AsRenderFrameHostIfValid() == render_frame_host) {
      run_loop_.Quit();
    }
  }

  // Block the running thread until the DOMContentLoaded event fires. Returns
  // true if the function returns as a result of the DOMContentLoaded event
  // being fired, false otherwise (e.g. timeout).
  [[nodiscard]] bool Wait() {
    CHECK(render_frame_host_.AsRenderFrameHostIfValid());
    if (render_frame_host_.AsRenderFrameHostIfValid()->IsDOMContentLoaded()) {
      run_loop_.Quit();
    }
    run_loop_.Run();
    CHECK(render_frame_host_.AsRenderFrameHostIfValid());
    return render_frame_host_.AsRenderFrameHostIfValid()->IsDOMContentLoaded();
  }

 private:
  WeakDocumentPtr render_frame_host_;
  base::RunLoop run_loop_;
};

}  // namespace

// Suspends execution in the current thread until the DOMContentLoaded event
// fires in the given RenderFrameHost. Note, this will only observe the Document
// associated with the given RenderFrameHost at the time of the call.
bool WaitForDOMContentLoaded(RenderFrameHost* rfh) {
  DOMContentLoadedObserver observer(rfh);
  return observer.Wait();
}

std::vector<RenderWidgetHost*> GetPopupWidgets(WebContents* web_contents) {
  std::vector<RenderWidgetHost*> popup_widgets;
  for (RenderWidgetHostView* view : static_cast<WebContentsImpl*>(web_contents)
                                        ->GetRenderWidgetHostViewsForTests()) {
    if (static_cast<RenderWidgetHostViewBase*>(view)->GetWidgetType() ==
        WidgetType::kPopup) {
      popup_widgets.push_back(view->GetRenderWidgetHost());
    }
  }
  return popup_widgets;
}

CreateNewPopupWidgetInterceptor::CreateNewPopupWidgetInterceptor(
    RenderFrameHost* rfh,
    base::OnceCallback<void(RenderWidgetHost*)> did_create_callback)
    : swapped_impl_(static_cast<RenderFrameHostImpl*>(rfh)
                        ->local_frame_host_receiver_for_testing(),
                    this),
      did_create_callback_(std::move(did_create_callback)) {}

CreateNewPopupWidgetInterceptor::~CreateNewPopupWidgetInterceptor() = default;

void CreateNewPopupWidgetInterceptor::CreateNewPopupWidget(
    mojo::PendingAssociatedReceiver<blink::mojom::PopupWidgetHost>
        blink_popup_widget_host,
    mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost> blink_widget_host,
    mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget) {
  class PopupWidgetCreationObserver : public RenderWidgetHostFactory {
   public:
    PopupWidgetCreationObserver() { RegisterFactory(this); }

    ~PopupWidgetCreationObserver() override { UnregisterFactory(); }

    // RenderWidgetHostFactory overrides:
    RenderWidgetHostImpl* CreateSelfOwnedRenderWidgetHost(
        FrameTree* frame_tree,
        RenderWidgetHostDelegate* delegate,
        base::SafeRef<SiteInstanceGroup> site_instance_group,
        int32_t routing_id,
        bool hidden) override {
      CHECK(!last_created_widget_);
      last_created_widget_ =
          RenderWidgetHostFactory::CreateSelfOwnedRenderWidgetHost(
              frame_tree, delegate, std::move(site_instance_group), routing_id,
              hidden);
      return last_created_widget_;
    }

    RenderWidgetHostImpl* TakeLastCreatedWidget() {
      return std::exchange(last_created_widget_, nullptr);
    }

   private:
    raw_ptr<RenderWidgetHostImpl> last_created_widget_;
  };

  PopupWidgetCreationObserver creation_observer;

  GetForwardingInterface()->CreateNewPopupWidget(
      std::move(blink_popup_widget_host), std::move(blink_widget_host),
      std::move(blink_widget));

  if (!did_create_callback_) {
    return;
  }

  if (auto* widget = creation_observer.TakeLastCreatedWidget(); widget) {
    std::move(did_create_callback_).Run(widget);
  }
}

blink::mojom::LocalFrameHost*
CreateNewPopupWidgetInterceptor::GetForwardingInterface() {
  return swapped_impl_.old_impl();
}

#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_ANDROID)
ShowPopupWidgetWaiter::ShowPopupMenuInterceptor::ShowPopupMenuInterceptor(
    RenderFrameHost* rfh,
    base::OnceCallback<void(const gfx::Rect&)> did_show_popup_menu_callback)
    : swapped_impl_(static_cast<RenderFrameHostImpl*>(rfh)
                        ->local_frame_host_receiver_for_testing(),
                    this),
      did_show_popup_menu_callback_(std::move(did_show_popup_menu_callback)) {}

ShowPopupWidgetWaiter::ShowPopupMenuInterceptor::~ShowPopupMenuInterceptor() =
    default;

void ShowPopupWidgetWaiter::ShowPopupMenuInterceptor::ShowPopupMenu(
    mojo::PendingRemote<blink::mojom::PopupMenuClient> popup_client,
    const gfx::Rect& bounds,
    double font_size,
    int32_t selected_item,
    std::vector<blink::mojom::MenuItemPtr> menu_items,
    bool right_aligned,
    bool allow_multiple_selection) {
  if (did_show_popup_menu_callback_) {
    std::move(did_show_popup_menu_callback_).Run(bounds);
    mojo::Remote<blink::mojom::PopupMenuClient>(std::move(popup_client))
        ->DidCancel();
    return;
  }

  GetForwardingInterface()->ShowPopupMenu(
      std::move(popup_client), bounds, font_size, selected_item,
      std::move(menu_items), right_aligned, allow_multiple_selection);
}

blink::mojom::LocalFrameHost*
ShowPopupWidgetWaiter::ShowPopupMenuInterceptor::GetForwardingInterface() {
  return swapped_impl_.old_impl();
}
#endif

ShowPopupWidgetWaiter::ShowPopupWidgetWaiter(WebContents* web_contents,
                                             RenderFrameHost* frame_host)
    : create_new_popup_widget_interceptor_(
          static_cast<RenderFrameHostImpl*>(frame_host),
          base::BindOnce(&ShowPopupWidgetWaiter::DidCreatePopupWidget,
                         base::Unretained(this))),
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_ANDROID)
      show_popup_menu_interceptor_(
          frame_host,
          base::BindOnce(&ShowPopupWidgetWaiter::DidShowPopupMenu,
                         base::Unretained(this))),
#endif

      frame_host_(frame_host) {
}

ShowPopupWidgetWaiter::~ShowPopupWidgetWaiter() {
  if (auto* rwhi = RenderWidgetHostImpl::FromID(process_id_, routing_id_)) {
    std::ignore =
        rwhi->popup_widget_host_receiver_for_testing().SwapImplForTesting(rwhi);
  }
}

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

blink::mojom::PopupWidgetHost* ShowPopupWidgetWaiter::GetForwardingInterface() {
  DCHECK_NE(IPC::mojom::kRoutingIdNone, routing_id_);
  return RenderWidgetHostImpl::FromID(process_id_, routing_id_);
}

void ShowPopupWidgetWaiter::ShowPopup(const gfx::Rect& initial_rect,
                                      const gfx::Rect& initial_anchor_rect,
                                      ShowPopupCallback callback) {
  GetForwardingInterface()->ShowPopup(initial_rect, initial_anchor_rect,
                                      std::move(callback));
  initial_rect_ = initial_rect;
  run_loop_.Quit();
}

void ShowPopupWidgetWaiter::DidCreatePopupWidget(
    RenderWidgetHost* render_widget_host) {
  process_id_ = render_widget_host->GetProcess()->GetDeprecatedID();
  routing_id_ = render_widget_host->GetRoutingID();
  // Swapped back in destructor from process_id_ and routing_id_ lookup.
  std::ignore = static_cast<RenderWidgetHostImpl*>(render_widget_host)
                    ->popup_widget_host_receiver_for_testing()
                    .SwapImplForTesting(this);
}

#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_ANDROID)
void ShowPopupWidgetWaiter::DidShowPopupMenu(const gfx::Rect& bounds) {
  initial_rect_ = bounds;
  run_loop_.Quit();
}
#endif

RequestCloseWidgetInterceptor::RequestCloseWidgetInterceptor(
    RenderWidgetHost* render_widget_host)
    : swapped_impl_(static_cast<RenderWidgetHostImpl*>(render_widget_host)
                        ->popup_widget_host_receiver_for_testing(),
                    this) {}

RequestCloseWidgetInterceptor::~RequestCloseWidgetInterceptor() = default;

blink::mojom::PopupWidgetHost*
RequestCloseWidgetInterceptor::GetForwardingInterface() {
  return swapped_impl_.old_impl();
}

void RequestCloseWidgetInterceptor::RequestClosePopup() {}

}  // namespace content
