// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// 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 <cstdint>
#include <set>
#include <tuple>
#include <utility>

#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/files/file_util.h"
#include "base/guid.h"
#include "base/json/json_reader.h"
#include "base/process/kill.h"
#include "base/run_loop.h"
#include "base/strings/pattern.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "base/task/post_task.h"
#include "base/test/bind.h"
#include "base/test/test_switches.h"
#include "base/test/test_timeouts.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/typed_macros.h"
#include "base/values.h"
#include "build/build_config.h"
#include "cc/test/pixel_test_utils.h"
#include "components/viz/client/frame_evictor.h"
#include "content/browser/accessibility/browser_accessibility.h"
#include "content/browser/accessibility/browser_accessibility_manager.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/input/synthetic_touchscreen_pinch_gesture.h"
#include "content/browser/renderer_host/navigation_request.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_impl.h"
#include "content/browser/renderer_host/render_widget_host_input_event_router.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/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/notification_service.h"
#include "content/public/browser/notification_types.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/storage_partition.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/use_zoom_for_dsf_policy.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/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 "ipc/ipc_security_test_util.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_util.h"
#include "net/cookies/same_party_context.h"
#include "net/filter/gzip_header.h"
#include "net/filter/gzip_source_stream.h"
#include "net/filter/mock_source_stream.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_service.mojom.h"
#include "services/network/public/mojom/network_service_test.mojom.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/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/filesystem/file_system.mojom.h"
#include "third_party/skia/include/core/SkBitmap.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/latency/latency_info.h"
#include "ui/resources/grit/webui_generated_resources.h"

#if defined(OS_WIN)
#include <combaseapi.h>
#include <uiautomation.h>
#include <wrl/client.h>
#include "base/win/scoped_safearray.h"
#include "base/win/scoped_variant.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 {

// Specifying a prototype so that we can add the WARN_UNUSED_RESULT attribute.
bool ExecuteScriptHelper(RenderFrameHost* render_frame_host,
                         const std::string& script,
                         bool user_gesture,
                         int32_t world_id,
                         std::unique_ptr<base::Value>* result)
    WARN_UNUSED_RESULT;

// Executes the passed |script| in the frame specified by |render_frame_host|.
// If |result| is not NULL, stores the value that the evaluation of the script
// in |result|.  Returns true on success.
bool ExecuteScriptHelper(RenderFrameHost* render_frame_host,
                         const std::string& script,
                         bool user_gesture,
                         int32_t world_id,
                         std::unique_ptr<base::Value>* result) {
  // TODO(lukasza): Only get messages from the specific |render_frame_host|.
  DOMMessageQueue dom_message_queue(render_frame_host);

  std::u16string script16 = base::UTF8ToUTF16(script);
  if (world_id == ISOLATED_WORLD_ID_GLOBAL && user_gesture) {
    render_frame_host->ExecuteJavaScriptWithUserGestureForTests(script16,
                                                                world_id);
  } else {
    // Note that |user_gesture| here is ignored when the world is not main. We
    // allow a value of |true| because it's the default, but in blink, the
    // execution will occur with no user gesture.
    render_frame_host->ExecuteJavaScriptForTests(script16, base::NullCallback(),
                                                 world_id);
  }

  std::string json;
  if (!dom_message_queue.WaitForMessage(&json)) {
    DLOG(ERROR) << "Cannot communicate with DOMMessageQueue.";
    return false;
  }

  // Nothing more to do for callers that ignore the returned JS value.
  if (!result)
    return true;

  base::JSONReader::ValueWithError parsed_json =
      base::JSONReader::ReadAndReturnValueWithError(
          json, base::JSON_ALLOW_TRAILING_COMMAS);
  if (!parsed_json.value) {
    *result = nullptr;
    DLOG(ERROR) << parsed_json.error_message;
    return false;
  }
  *result = base::Value::ToUniquePtrValue(std::move(*parsed_json.value));

  return true;
}

bool ExecuteScriptWithUserGestureControl(RenderFrameHost* frame,
                                         const std::string& script,
                                         bool user_gesture) {
  // TODO(lukasza): ExecuteScript should just call
  // ExecuteJavaScriptWithUserGestureForTests and avoid modifying the original
  // script (and at that point we should merge it with and remove
  // ExecuteScriptAsync).  This is difficult to change, because many tests
  // depend on the message loop pumping done by ExecuteScriptHelper below (this
  // is fragile - these tests should wait on a more specific thing instead).

  // TODO(nick): This function can't be replaced with a call to ExecJs(), since
  // ExecJs calls eval() which might be blocked by the page's CSP.
  std::string expected_response = "ExecuteScript-" + base::GenerateGUID();
  std::string new_script = base::StringPrintf(
      R"( %s;  // Original script.
          window.domAutomationController.send('%s'); )",
      script.c_str(), expected_response.c_str());

  std::unique_ptr<base::Value> value;
  if (!ExecuteScriptHelper(frame, new_script, user_gesture,
                           ISOLATED_WORLD_ID_GLOBAL, &value) ||
      !value.get()) {
    return false;
  }

  DCHECK_EQ(base::Value::Type::STRING, value->type());
  std::string actual_response;
  if (value->GetAsString(&actual_response))
    DCHECK_EQ(expected_response, actual_response);

  return true;
}

void BuildSimpleWebKeyEvent(blink::WebInputEvent::Type type,
                            ui::DomKey key,
                            ui::DomCode code,
                            ui::KeyboardCode key_code,
                            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_in_browser = 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) {
  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->GetMainFrame()->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(base::StringPiece(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(
      NavigationHandle* handle,
      base::OnceClosure on_will_start_request_closure,
      base::OnceClosure on_will_process_response_closure)
      : NavigationThrottle(handle),
        on_will_start_request_closure_(
            std::move(on_will_start_request_closure)),
        on_will_process_response_closure_(
            std::move(on_will_process_response_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 WillProcessResponse() override {
    DCHECK(on_will_process_response_closure_);
    GetUIThreadTaskRunner({})->PostTask(
        FROM_HERE, std::move(on_will_process_response_closure_));
    return NavigationThrottle::DEFER;
  }

  base::OnceClosure on_will_start_request_closure_;
  base::OnceClosure on_will_process_response_closure_;
};

bool HasGzipHeader(const base::RefCountedMemory& maybe_gzipped) {
  net::GZipHeader header;
  net::GZipHeader::Status header_status = net::GZipHeader::INCOMPLETE_HEADER;
  const char* header_end = nullptr;
  while (header_status == net::GZipHeader::INCOMPLETE_HEADER) {
    header_status = header.ReadMore(maybe_gzipped.front_as<char>(),
                                    maybe_gzipped.size(),
                                    &header_end);
  }
  return header_status == net::GZipHeader::COMPLETE_HEADER;
}

void AppendGzippedResource(const base::RefCountedMemory& encoded,
                           std::string* to_append) {
  auto source_stream = std::make_unique<net::MockSourceStream>();
  source_stream->AddReadResult(encoded.front_as<char>(), encoded.size(),
                               net::OK, net::MockSourceStream::SYNC);
  // Add an EOF.
  source_stream->AddReadResult(encoded.front_as<char>() + encoded.size(), 0,
                               net::OK, net::MockSourceStream::SYNC);
  std::unique_ptr<net::GzipSourceStream> filter = net::GzipSourceStream::Create(
      std::move(source_stream), net::SourceStream::TYPE_GZIP);
  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);
  }
}

// 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() {
      navigator.mediaDevices.enumerateDevices()
      .then(function(devices) {
        if (devices.some((device) => device.kind == 'videoinput')) {
          window.domAutomationController.send('has-video-input-device');
        } else {
          window.domAutomationController.send('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:
  RenderWidgetHost* widget_host_;
  base::RunLoop run_loop_;
  base::RepeatingCallback<bool()> is_complete_callback_;
};

#if defined(USE_AURA)

class BoundingBoxUpdateWaiter : public TextInputManager::Observer {
 public:
  explicit BoundingBoxUpdateWaiter(RenderWidgetHostViewAura* rwhva)
      : text_input_manager_(rwhva->GetTextInputManager()),
        original_bounding_box_(rwhva->GetSelectionBoundingBox()),
        rwhva_(rwhva) {
    text_input_manager_->AddObserver(this);
  }
  BoundingBoxUpdateWaiter(const BoundingBoxUpdateWaiter&) = delete;
  BoundingBoxUpdateWaiter& operator=(const BoundingBoxUpdateWaiter&) = delete;
  ~BoundingBoxUpdateWaiter() { text_input_manager_->RemoveObserver(this); }

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

 private:
  // TextInputManager::Observer:
  void OnSelectionBoundsChanged(
      TextInputManager* text_input_manager,
      RenderWidgetHostViewBase* updated_view) override {
    if (rwhva_->GetSelectionBoundingBox() == original_bounding_box_) {
      return;
    }

    run_loop_.Quit();
  }

  TextInputManager* const text_input_manager_;
  const gfx::Rect original_bounding_box_;
  RenderWidgetHostViewAura* const rwhva_;

  base::RunLoop run_loop_;
};

#endif

// 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();
}

}  // namespace

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) {
  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() == url;
}

bool BeginNavigateToURLFromRenderer(const ToRenderFrameHost& adapter,
                                    const GURL& url) {
  return ExecJs(adapter, JsReplace("location = $1", url));
}

bool NavigateIframeToURL(WebContents* web_contents,
                         const std::string& 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,
                              const std::string& iframe_id,
                              const GURL& url) {
  std::string script = base::StringPrintf(
      "setTimeout(\""
      "var iframes = document.getElementById('%s');iframes.src='%s';"
      "\",0)",
      iframe_id.c_str(), url.spec().c_str());
  return ExecuteScriptWithoutUserGesture(web_contents, script);
}

void NavigateToURLBlockUntilNavigationsComplete(
    WebContents* web_contents,
    const GURL& url,
    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(url) && number_of_navigations == 1)
    same_tab_observer.set_expected_initial_url(url);

  // 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);
  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,
                         const std::string& 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<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();
  return "";
}

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()->SetActive(
      active);
}

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()) {
    WindowedNotificationObserver load_stop_observer(
        NOTIFICATION_LOAD_STOP,
        Source<NavigationController>(&web_contents->GetController()));
    load_stop_observer.Wait();
  }
}

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;
  }
  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;
}

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

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

bool IsLastCommittedEntryOfPageType(WebContents* web_contents,
                                    content::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->GetMainFrame()->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 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);
}

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->GetMainFrame()->GetRenderViewHost()->GetWidget());
  if (!IsResizeComplete(&dispatcher_test, widget_host)) {
    ResizeObserver resize_observer(
        widget_host,
        base::BindRepeating(IsResizeComplete, &dispatcher_test, widget_host));
    resize_observer.Wait();
  }
}
#elif defined(OS_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 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(
    content::WebContents* web_contents,
    const std::string& id) {
  float x = EvalJs(web_contents,
                   JsReplace("const bounds = "
                             "document.getElementById($1)."
                             "getBoundingClientRect();"
                             "Math.floor(bounds.left + bounds.width / 2)",
                             id))
                .ExtractDouble();
  float y = EvalJs(web_contents,
                   JsReplace("const bounds = "
                             "document.getElementById($1)."
                             "getBoundingClientRect();"
                             "Math.floor(bounds.top + bounds.height / 2)",
                             id))
                .ExtractDouble();
  return gfx::PointF(x, y);
}

void SimulateMouseClickOrTapElementWithId(content::WebContents* web_contents,
                                          const std::string& id) {
  gfx::Point point = gfx::ToFlooredPoint(
      GetCenterCoordinatesOfElementWithId(web_contents, id));

#if defined(OS_ANDROID)
  SimulateTapDownAt(web_contents, point);
  SimulateTapAt(web_contents, point);
#else
  SimulateMouseClickAt(web_contents, 0, blink::WebMouseEvent::Button::kLeft,
                       point);
#endif  // defined(OS_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->GetMainFrame()->GetRenderViewHost()->GetWidget());
  widget_host->ForwardWheelEvent(wheel_event);
}

#if !defined(OS_MAC)
void SimulateMouseWheelCtrlZoomEvent(WebContents* web_contents,
                                     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(
      web_contents->GetMainFrame()->GetRenderViewHost()->GetWidget());
  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 = content::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  // !defined(OS_MAC)

void SimulateGesturePinchSequence(WebContents* web_contents,
                                  const gfx::Point& point,
                                  float scale,
                                  blink::WebGestureDevice source_device) {
  RenderWidgetHostImpl* widget_host = RenderWidgetHostImpl::From(
      web_contents->GetMainFrame()->GetRenderViewHost()->GetWidget());

  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 SimulateGestureScrollSequence(WebContents* web_contents,
                                   const gfx::Point& point,
                                   const gfx::Vector2dF& delta) {
  RenderWidgetHostImpl* widget_host = RenderWidgetHostImpl::From(
      web_contents->GetMainFrame()->GetRenderViewHost()->GetWidget());

  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();
  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();
  scroll_update.data.scroll_update.velocity_x = 0;
  scroll_update.data.scroll_update.velocity_y = 0;
  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));
  widget_host->ForwardGestureEvent(scroll_end);
}

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->GetMainFrame()->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->GetMainFrame()->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::ET_TOUCH_PRESSED, point, base::TimeTicks(),
      ui::PointerDetails(ui::EventPointerType::kTouch, 0));
  rwhva->OnTouchEvent(&touch_start);

  ui::GestureEventDetails tap_down_details(ui::ET_GESTURE_TAP_DOWN);
  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::ET_GESTURE_LONG_PRESS);
  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::ET_TOUCH_RELEASED, point, base::TimeTicks(),
                           ui::PointerDetails(ui::EventPointerType::kTouch, 0));
  rwhva->OnTouchEvent(&touch_end);

  ui::GestureEventDetails long_tap_details(ui::ET_GESTURE_LONG_TAP);
  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);
}

void WaitForSelectionBoundingBoxUpdate(WebContents* web_contents) {
  RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
      web_contents->GetRenderWidgetHostView());
  BoundingBoxUpdateWaiter waiter(rwhva);
  waiter.Wait();
}
#endif

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);
}

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) {
  std::string result;
  EXPECT_TRUE(ExecuteScriptAndExtractString(
      web_contents, kHasVideoInputDeviceOnSystem, &result));
  return result == kHasVideoInputDevice;
}

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

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

bool ExecuteScript(const ToRenderFrameHost& adapter,
                   const std::string& script) {
  return ExecuteScriptWithUserGestureControl(adapter.render_frame_host(),
                                             script, true);
}

bool ExecuteScriptWithoutUserGesture(const ToRenderFrameHost& adapter,
                                     const std::string& script) {
  return ExecuteScriptWithUserGestureControl(adapter.render_frame_host(),
                                             script, false);
}

void ExecuteScriptAsync(const ToRenderFrameHost& adapter,
                        const std::string& script) {
  adapter.render_frame_host()->ExecuteJavaScriptWithUserGestureForTests(
      base::UTF8ToUTF16(script));
}

bool ExecuteScriptAndExtractDouble(const ToRenderFrameHost& adapter,
                                   const std::string& script, double* result) {
  DCHECK(result);
  std::unique_ptr<base::Value> value;
  if (!ExecuteScriptHelper(adapter.render_frame_host(), script, true,
                           ISOLATED_WORLD_ID_GLOBAL, &value))
    return false;
  if (!value)
    return false;
  absl::optional<double> maybe_value = value->GetIfDouble();
  if (!maybe_value.has_value())
    return false;

  *result = maybe_value.value();
  return true;
}

bool ExecuteScriptAndExtractInt(const ToRenderFrameHost& adapter,
                                const std::string& script, int* result) {
  DCHECK(result);
  std::unique_ptr<base::Value> value;
  if (ExecuteScriptHelper(adapter.render_frame_host(), script, true,
                          ISOLATED_WORLD_ID_GLOBAL, &value) &&
      value && value->is_int() && result) {
    *result = value->GetInt();
    return true;
  }
  return false;
}

bool ExecuteScriptAndExtractBool(const ToRenderFrameHost& adapter,
                                 const std::string& script, bool* result) {
  DCHECK(result);
  std::unique_ptr<base::Value> value;
  return ExecuteScriptHelper(adapter.render_frame_host(), script, true,
                             ISOLATED_WORLD_ID_GLOBAL, &value) &&
         value && value->GetAsBoolean(result);
}

bool ExecuteScriptAndExtractString(const ToRenderFrameHost& adapter,
                                   const std::string& script,
                                   std::string* result) {
  DCHECK(result);
  std::unique_ptr<base::Value> value;
  return ExecuteScriptHelper(adapter.render_frame_host(), script, true,
                             ISOLATED_WORLD_ID_GLOBAL, &value) &&
         value && value->GetAsString(result);
}

bool ExecuteScriptWithoutUserGestureAndExtractBool(
    const ToRenderFrameHost& adapter,
    const std::string& script,
    bool* result) {
  DCHECK(result);
  std::unique_ptr<base::Value> value;
  return ExecuteScriptHelper(adapter.render_frame_host(), script, false,
                             ISOLATED_WORLD_ID_GLOBAL, &value) &&
         value && value->GetAsBoolean(result);
}

bool ExecuteScriptWithoutUserGestureAndExtractString(
    const ToRenderFrameHost& adapter,
    const std::string& script,
    std::string* result) {
  DCHECK(result);
  std::unique_ptr<base::Value> value;
  return ExecuteScriptHelper(adapter.render_frame_host(), script, false,
                             ISOLATED_WORLD_ID_GLOBAL, &value) &&
         value && value->GetAsString(result);
}

// EvalJsResult methods.
EvalJsResult::EvalJsResult(base::Value value, const std::string& error)
    : value(error.empty() ? std::move(value) : base::Value()), error(error) {}

EvalJsResult::EvalJsResult(const EvalJsResult& other)
    : value(other.value.Clone()), error(other.error) {}

const std::string& EvalJsResult::ExtractString() const {
  CHECK(error.empty())
      << "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(error.empty())
      << "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(error.empty())
      << "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(error.empty())
      << "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();
}

base::ListValue EvalJsResult::ExtractList() const {
  CHECK(error.empty())
      << "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 base::ListValue(value.GetList());
}

void PrintTo(const EvalJsResult& bar, ::std::ostream* os) {
  if (!bar.error.empty()) {
    *os << bar.error;
  } else {
    *os << bar.value;
  }
}

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 ExecuteScript 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(const std::string& js_error,
                                           std::string source_name,
                                           const std::string& 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<base::StringPiece> 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 base::StringPiece 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 (const base::StringPiece& 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<base::StringPiece> 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();
}

EvalJsResult EvalRunnerScript(const ToRenderFrameHost& execution_target,
                              const std::string& script,
                              int options,
                              int32_t world_id,
                              const std::string& token) {
  const char* kSourceURL = "__const_std::string&_script__";
  bool use_automatic_reply = !(options & EXECUTE_SCRIPT_USE_MANUAL_REPLY);
  bool user_gesture = !(options & EXECUTE_SCRIPT_NO_USER_GESTURE);
  std::ostringstream error_stream;
  std::unique_ptr<base::Value> response;
  if (!execution_target.render_frame_host()->IsRenderFrameLive()) {
    error_stream << "Error: EvalJs won't work on an already-crashed frame.";
  } else if (!ExecuteScriptHelper(execution_target.render_frame_host(), script,
                                  user_gesture, world_id, &response)) {
    error_stream << "Internal Error: ExecuteScriptHelper failed";
  } else if (!response) {
    error_stream << "Internal Error: no value";
  } else {
    bool is_reply_from_script = response->is_list() &&
                                response->GetList().size() == 2 &&
                                response->GetList()[0].is_string() &&
                                response->GetList()[0].GetString() == token;

    bool is_error = is_reply_from_script && response->GetList()[1].is_string();
    bool is_automatic_success_reply =
        is_reply_from_script && response->GetList()[1].is_list() &&
        response->GetList()[1].GetList().size() == 1;

    if (is_error) {
      // This is a response generated by the error handler in our runner
      // script. This occurs when the script throws an exception, or when
      // eval throws a SyntaxError.
      //
      // Parse the stack trace here, and interleave lines of source code from
      // |script| to aid debugging.
      std::string error_text = response->GetList()[1].GetString();

      if (base::StartsWith(error_text,
                           "a JavaScript error:\nEvalError: Refused",
                           base::CompareCase::SENSITIVE)) {
        error_text =
            "EvalJs 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 EvalJs with an isolated world. Details: " +
            error_text;
      }

      CHECK(!error_text.empty());
      error_stream << AnnotateAndAdjustJsStackTraces(error_text, kSourceURL,
                                                     script, 0);
    } else if (!use_automatic_reply) {
      // When |script| itself calls domAutomationController.send() on success,
      // |response| could be anything; so there's no more checking we can do:
      // return |response| as success, with an empty error.
      return EvalJsResult(std::move(*response), std::string());
    } else if (is_automatic_success_reply) {
      // Got a response from the runner script that indicates success (of the
      // form [token, [completion_value]]. Return the completion value, with an
      // empty error.
      return EvalJsResult(std::move(response->GetList()[1].GetList()[0]),
                          std::string());
    } else {
      // The response was not well-formed (it failed the token match), so it's
      // not from our runner script. Fail with an explanation of the raw
      // message. This allows us to reject other calls
      // domAutomationController.send().
      error_stream
          << "Internal Error: expected a 2-element list of the form "
          << "['" << token << "', [result]]; but got instead: " << *response
          << " ... This is potentially because a script tried to call "
             "domAutomationController.send itself -- that is only allowed "
             "when using EXECUTE_SCRIPT_USE_MANUAL_REPLY.  When using "
             "EvalJs(), result values are just the result of calling eval() on "
             "the script -- the completion value is the value of the last "
             "executed statement.  When using ExecJs(), there is no result "
             "value.";
    }
  }

  // Something went wrong. Return an empty value and a non-empty error.
  return EvalJsResult(base::Value(), error_stream.str());
}

}  // namespace

::testing::AssertionResult ExecJs(const ToRenderFrameHost& execution_target,
                                  const std::string& script,
                                  int options,
                                  int32_t world_id) {
  CHECK(!(options & EXECUTE_SCRIPT_USE_MANUAL_REPLY))
      << "USE_MANUAL_REPLY does not make sense with ExecJs.";

  // 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.error.empty())
    return ::testing::AssertionFailure() << eval_result.error;
  return ::testing::AssertionSuccess();
}

EvalJsResult EvalJs(const ToRenderFrameHost& execution_target,
                    const std::string& script,
                    int options,
                    int32_t world_id) {
  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.
  const char* kSourceURL = "__const_std::string&_script__";
  std::string modified_script =
      base::StringPrintf("%s;\n//# sourceURL=%s", script.c_str(), kSourceURL);

  // An extra eval() indirection is used here to catch syntax errors and return
  // them as assertion failures. This eval() operation deliberately occurs in
  // the global scope, so 'var' declarations in |script| will persist for later
  // script executions. (As an aside: global/local scope for eval depends on
  // whether 'eval' is called directly or indirectly; 'window.eval()' is
  // indirect).
  //
  // The call to eval() itself is inside a .then() handler so that syntax errors
  // result in Promise rejection. Calling eval() either throws (in the event of
  // a SyntaxError) or returns the script's completion value.
  //
  // The result of eval() (i.e., the statement completion value of |script|) is
  // wrapped in an array and passed to a second .then() handler. If eval()
  // returned a Promise and the |resolve_promises| option is set, this handler
  // calls Promise.all to reply after the returned Promise resolves.
  //
  // If |script| evaluated successfully, the third.then() handler maps the
  // resolved |result| of eval() to a |reply| that is a one-element list
  // containing the value (this element can be any JSON-serializable type). If
  // the manual reply option is being used, no reply is emitted after successful
  // execution -- the script is expected to call send() itself. The call to
  // Promise.reject() squelches this reply, and the final .then() handler is not
  // called.
  //
  // If an uncaught error was thrown, or eval() returns a Promise that is
  // rejected, the third .then() handler maps the |error| to a |reply| that is
  // a string value.
  //
  // The fourth and final .then() handler passes the |reply| (whether
  // successful or unsuccessful) to domAutomationController.send(), so that it's
  // transmitted back here in browser process C++ land. A GUID token is also
  // included, that protects against |script| directly calling
  // domAutomationController.send() itself, which is disallowed in EvalJs.
  bool use_automatic_reply = !(options & EXECUTE_SCRIPT_USE_MANUAL_REPLY);
  bool resolve_promises = !(options & EXECUTE_SCRIPT_NO_RESOLVE_PROMISES);

  std::string token = "EvalJs-" + base::GenerateGUID();
  std::string runner_script = JsReplace(
      R"(Promise.resolve($1)
         .then(script => [window.eval(script)])
         .then((result) => $2 ? Promise.all(result) : result )
         .then((result) => $3 ? result : Promise.reject(),
               (error) => 'a JavaScript error:' +
                          (error && error.stack ? '\n' + error.stack
                                                : ' "' + error + '"'))
         .then((reply) => window.domAutomationController.send([$4, reply]));
      //# sourceURL=EvalJs-runner.js)",
      modified_script, resolve_promises, use_automatic_reply, token);

  return EvalRunnerScript(execution_target, runner_script, options, world_id,
                          token);
}

EvalJsResult EvalJsAfterLifecycleUpdate(
    const ToRenderFrameHost& execution_target,
    const std::string& raf_script,
    const std::string& script,
    int options,
    int32_t world_id) {
  bool use_automatic_reply = !(options & EXECUTE_SCRIPT_USE_MANUAL_REPLY);
  bool resolve_promises = !(options & EXECUTE_SCRIPT_NO_RESOLVE_PROMISES);
  std::string token = "EvalJs-" + base::GenerateGUID();
  const char* kSourceURL = "__const_std::string&_script__";
  std::string modified_raf_script;
  if (raf_script.length()) {
    modified_raf_script = base::StringPrintf("%s;\n//# sourceURL=%s",
                                             raf_script.c_str(), kSourceURL);
  }
  std::string modified_script =
      base::StringPrintf("%s;\n//# sourceURL=%s", script.c_str(), kSourceURL);

  // This runner_script is very similar to that used by EvalJs, except that
  // this one delays running the argument script until just before
  // (|raf_script|) and after (|script|) a rendering update.
  std::string runner_script = JsReplace(
      R"(Promise.all([$1, $2])
         .then(scripts => new Promise((resolve, reject) => {
               requestAnimationFrame(() => {
                 window.eval(scripts[0]);
                 setTimeout(() => {
                   resolve([window.eval(scripts[1])])
                 }) }) }) )
         .then((result) => $3 ? Promise.all(result) : result )
         .then((result) => $4 ? result : Promise.reject(),
               (error) => 'a JavaScript error:' +
                          (error && error.stack ? '\n' + error.stack
                                                : ' "' + error + '"'))
         .then((reply) => window.domAutomationController.send([$5, reply]));
      //# sourceURL=EvalJs-runner.js)",
      modified_raf_script, modified_script, resolve_promises,
      use_automatic_reply, token);

  return EvalRunnerScript(execution_target, runner_script, options, world_id,
                          token);
}

namespace {
void AddToSetIfFrameMatchesPredicate(
    std::set<RenderFrameHost*>* frame_set,
    base::OnceCallback<bool(RenderFrameHost*)> predicate,
    RenderFrameHost* host) {
  if (std::move(predicate).Run(host))
    frame_set->insert(host);
}
}

RenderFrameHost* FrameMatchingPredicate(
    Page& page,
    base::RepeatingCallback<bool(RenderFrameHost*)> predicate) {
  std::set<RenderFrameHost*> frame_set;
  page.GetMainDocument().ForEachRenderFrameHost(base::BindRepeating(
      &AddToSetIfFrameMatchesPredicate, &frame_set, predicate));
  EXPECT_EQ(1U, frame_set.size());
  return frame_set.size() == 1 ? *frame_set.begin() : nullptr;
}

bool FrameMatchesName(const std::string& 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();
}

std::vector<RenderFrameHost*> CollectAllRenderFrameHosts(
    RenderFrameHost* starting_rfh) {
  std::vector<RenderFrameHost*> visited_frames;
  starting_rfh->ForEachRenderFrameHost(base::BindLambdaForTesting(
      [&](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(base::BindLambdaForTesting(
      [&](RenderFrameHost* rfh) { visited_frames.push_back(rfh); }));
  return visited_frames;
}

bool ExecuteWebUIResourceTest(WebContents* web_contents,
                              const std::vector<int>& js_resource_ids) {
  // Inject WebUI test runner script first prior to other scripts required to
  // run the test as scripts may depend on it being declared.
  std::vector<int> ids;
  ids.push_back(IDR_WEBUI_JS_WEBUI_RESOURCE_TEST_JS);
  ids.insert(ids.end(), js_resource_ids.begin(), js_resource_ids.end());

  std::string script;
  for (int id : ids) {
    scoped_refptr<base::RefCountedMemory> bytes =
        ui::ResourceBundle::GetSharedInstance().LoadDataResourceBytes(id);

    if (HasGzipHeader(*bytes))
      AppendGzippedResource(*bytes, &script);
    else
      script.append(bytes->front_as<char>(), bytes->size());

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

  DOMMessageQueue message_queue;

  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;
}

std::string GetCookies(BrowserContext* browser_context,
                       const GURL& url,
                       net::CookieOptions::SameSiteCookieContext context) {
  std::string cookies;
  base::RunLoop run_loop;
  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);
  cookie_manager->GetCookieList(
      url, options, net::CookiePartitionKeychain(),
      base::BindOnce(
          [](std::string* cookies_out, base::RunLoop* run_loop,
             const net::CookieAccessResultList& cookies,
             const net::CookieAccessResultList& excluded_cookies) {
            *cookies_out = net::CanonicalCookie::BuildCookieLine(cookies);
            run_loop->Quit();
          },
          &cookies, &run_loop));
  run_loop.Run();
  return cookies;
}

std::vector<net::CanonicalCookie> GetCanonicalCookies(
    BrowserContext* browser_context,
    const GURL& url) {
  std::vector<net::CanonicalCookie> cookies;
  base::RunLoop run_loop;
  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());
  cookie_manager->GetCookieList(
      url, options, net::CookiePartitionKeychain(),
      base::BindOnce(
          [](base::RunLoop* run_loop,
             std::vector<net::CanonicalCookie>* cookies_out,
             const net::CookieAccessResultList& cookies,
             const net::CookieAccessResultList& excluded_cookies) {
            *cookies_out = net::cookie_util::StripAccessResults(cookies);
            run_loop->Quit();
          },
          &run_loop, &cookies));
  run_loop.Run();
  return cookies;
}

bool SetCookie(BrowserContext* browser_context,
               const GURL& url,
               const std::string& value,
               net::CookieOptions::SameSiteCookieContext context,
               net::SamePartyContext::Type party_context) {
  bool result = false;
  base::RunLoop run_loop;
  mojo::Remote<network::mojom::CookieManager> cookie_manager;
  browser_context->GetDefaultStoragePartition()
      ->GetNetworkContext()
      ->GetCookieManager(cookie_manager.BindNewPipeAndPassReceiver());
  std::unique_ptr<net::CanonicalCookie> cc(net::CanonicalCookie::Create(
      url, value, base::Time::Now(), absl::nullopt /* server_time */,
      absl::nullopt /* cookie_partition_key */));
  DCHECK(cc.get());

  net::CookieOptions options;
  options.set_include_httponly();
  options.set_same_site_cookie_context(context);
  options.set_same_party_context(net::SamePartyContext(party_context));
  cookie_manager->SetCanonicalCookie(
      *cc.get(), url, options,
      base::BindOnce(
          [](bool* result, base::RunLoop* run_loop,
             net::CookieAccessResult set_cookie_access_result) {
            *result = set_cookie_access_result.status.IsInclude();
            run_loop->Quit();
          },
          &result, &run_loop));
  run_loop.Run();
  return result;
}

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

  uint32_t result = 0U;
  cookie_manager->DeleteCookies(
      network::mojom::CookieDeletionFilter::New(filter),
      base::BindOnce(
          [](uint32_t* result, base::RunLoop* run_loop,
             uint32_t cookies_cleared) {
            *result = cookies_cleared;
            run_loop->Quit();
          },
          &result, &run_loop));

  run_loop.Run();
  return result;
}

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::ThreadTaskRunnerHandle::Get(), 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<content::FileSystemAccessManagerImpl*>(
      browser_context->GetDefaultStoragePartition()
          ->GetFileSystemAccessEntryFactory())
      ->SetPermissionContextForTesting(permission_context);
}

bool WaitForRenderFrameReady(RenderFrameHost* rfh) {
  if (!rfh)
    return false;
  // TODO(nick): This can't switch to EvalJs yet, because of hardcoded
  // dependencies on 'pageLoadComplete' in some interstitial implementations.
  std::string result;
  EXPECT_TRUE(ExecuteScriptWithoutUserGestureAndExtractString(
      rfh,
      "(async function() {"
      "  if (document.readyState != 'complete') {"
      "    await new Promise((resolve) =>"
      "      document.addEventListener('readystatechange', event => {"
      "        if (document.readyState == 'complete') {"
      "          resolve();"
      "        }"
      "      }));"
      "  }"
      "})().then(() => {"
      "  window.domAutomationController.send('pageLoadComplete');"
      "});",
      &result));
  EXPECT_EQ("pageLoadComplete", result);
  return "pageLoadComplete" == result;
}

void EnableAccessibilityForWebContents(WebContents* web_contents) {
  WebContentsImpl* web_contents_impl =
      static_cast<WebContentsImpl*>(web_contents);
  web_contents_impl->SetAccessibilityMode(ui::kAXModeComplete);
}

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

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

bool AccessibilityTreeContainsNodeWithName(BrowserAccessibility* node,
                                           const std::string& 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, ui::AXMode(), ax::mojom::Event::kNone);
  accessibility_waiter.WaitForNotification();
}

void WaitForAccessibilityTreeToContainNodeWithName(WebContents* web_contents,
                                                   const std::string& name) {
  WebContentsImpl* web_contents_impl = static_cast<WebContentsImpl*>(
      web_contents);
  RenderFrameHostImpl* main_frame = static_cast<RenderFrameHostImpl*>(
      web_contents_impl->GetMainFrame());
  BrowserAccessibilityManager* main_frame_manager =
      main_frame->browser_accessibility_manager();
  while (!main_frame_manager || !AccessibilityTreeContainsNodeWithName(
             main_frame_manager->GetRoot(), 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);
  BrowserAccessibilityManager* manager =
      web_contents_impl->GetRootBrowserAccessibilityManager();
  if (!manager)
    return ui::AXTreeUpdate();
  return manager->SnapshotAXTreeForTesting();
}

ui::AXTreeUpdate GetAccessibilityTreeSnapshotFromId(
    const ui::AXTreeID& tree_id) {
  BrowserAccessibilityManager* manager =
      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);
  BrowserAccessibilityManager* manager =
      web_contents_impl->GetRootBrowserAccessibilityManager();
  return manager ? manager->GetRoot() : 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 = 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) {
    BrowserAccessibility* child = node_internal->PlatformGetChild(i);
    ui::AXPlatformNodeDelegate* result =
        FindAccessibilityNodeInSubtree(child, criteria);
    if (result)
      return result;
  }
  return nullptr;
}

#if defined(OS_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();
}

bool RequestKeyboardLock(WebContents* web_contents,
                         absl::optional<base::flat_set<ui::DomCode>> codes) {
  DCHECK(!codes.has_value() || !codes.value().empty());
  WebContentsImpl* web_contents_impl =
      static_cast<WebContentsImpl*>(web_contents);
  RenderWidgetHostImpl* render_widget_host_impl =
      web_contents_impl->GetMainFrame()->GetRenderWidgetHost();
  return render_widget_host_impl->RequestKeyboardLock(std::move(codes));
}

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

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

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

RenderWidgetHost* GetFocusedRenderWidgetHost(WebContents* web_contents) {
  WebContentsImpl* web_contents_impl =
      static_cast<WebContentsImpl*>(web_contents);
  return web_contents_impl->GetFocusedRenderWidgetHost(
      web_contents_impl->GetMainFrame()->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* RenderFrameMetadataProviderFromFrameTreeNode(
    FrameTreeNode* node) {
  DCHECK(node);
  DCHECK(node->current_frame_host());
  DCHECK(node->current_frame_host()->GetRenderWidgetHost());
  return node->current_frame_host()
      ->GetRenderWidgetHost()
      ->render_frame_metadata_provider();
}

RenderFrameMetadataProviderImpl* RenderFrameMetadataProviderFromWebContents(
    WebContents* web_contents) {
  DCHECK(web_contents);
  DCHECK(web_contents->GetMainFrame()->GetRenderViewHost());
  DCHECK(RenderWidgetHostImpl::From(
             web_contents->GetMainFrame()->GetRenderViewHost()->GetWidget())
             ->render_frame_metadata_provider());
  return RenderWidgetHostImpl::From(
             web_contents->GetMainFrame()->GetRenderViewHost()->GetWidget())
      ->render_frame_metadata_provider();
}

}  // namespace

TitleWatcher::TitleWatcher(WebContents* web_contents,
                           const std::u16string& expected_title)
    : WebContentsObserver(web_contents) {
  expected_titles_.push_back(expected_title);
}

void TitleWatcher::AlsoWaitForTitle(const std::u16string& expected_title) {
  expected_titles_.push_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->GetMainFrame()->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,
    const std::string& uma_name)
    : exit_watcher_(render_process_host,
                    RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT),
      uma_name_(uma_name) {}

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

  // Wait for the renderer kill.
  exit_watcher_.Wait();
#if !defined(OS_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());
}

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

  return observed_mojo_error_;
}

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

DOMMessageQueue::DOMMessageQueue() {
  registrar_.Add(this, NOTIFICATION_DOM_OPERATION_RESPONSE,
                 NotificationService::AllSources());
}

DOMMessageQueue::DOMMessageQueue(WebContents* web_contents)
    : WebContentsObserver(web_contents) {
  registrar_.Add(this, NOTIFICATION_DOM_OPERATION_RESPONSE,
                 Source<WebContents>(web_contents));
}

DOMMessageQueue::DOMMessageQueue(RenderFrameHost* render_frame_host)
    : DOMMessageQueue(WebContents::FromRenderFrameHost(render_frame_host)) {
  render_frame_host_ = render_frame_host;
}

DOMMessageQueue::~DOMMessageQueue() = default;

void DOMMessageQueue::Observe(int type,
                              const NotificationSource& source,
                              const NotificationDetails& details) {
  Details<std::string> dom_op_result(details);
  message_queue_.push(*dom_op_result.ptr());
  if (quit_closure_)
    std::move(quit_closure_).Run();
}

void DOMMessageQueue::RenderProcessGone(base::TerminationStatus status) {
  VLOG(0) << "DOMMessageQueue::RenderProcessGone " << status;
  switch (status) {
    case base::TERMINATION_STATUS_NORMAL_TERMINATION:
    case base::TERMINATION_STATUS_STILL_RUNNING:
      break;
    default:
      renderer_crashed_ = true;
      if (quit_closure_)
        std::move(quit_closure_).Run();
      break;
  }
}

void DOMMessageQueue::RenderFrameDeleted(RenderFrameHost* render_frame_host) {
  if (!render_frame_host_)
    return;
  if (render_frame_host_ != render_frame_host)
    return;
  if (quit_closure_)
    std::move(quit_closure_).Run();
}

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

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};
    quit_closure_ = 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;
}

WebContentsAddedObserver::WebContentsAddedObserver()
    : web_contents_created_callback_(
          base::BindRepeating(&WebContentsAddedObserver::WebContentsCreated,
                              base::Unretained(this))),
      web_contents_(nullptr) {
  WebContentsImpl::FriendWrapper::AddCreatedCallbackForTesting(
      web_contents_created_callback_);
}

WebContentsAddedObserver::~WebContentsAddedObserver() {
  WebContentsImpl::FriendWrapper::RemoveCreatedCallbackForTesting(
      web_contents_created_callback_);
}

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->GetMainFrame()->GetRenderViewHost()->GetWidget())
      ->RequestRepaintForTesting();
}

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

RenderFrameSubmissionObserver::RenderFrameSubmissionObserver(
    FrameTreeNode* node)
    : RenderFrameSubmissionObserver(
          RenderFrameMetadataProviderFromFrameTreeNode(node)) {}

RenderFrameSubmissionObserver::RenderFrameSubmissionObserver(
    WebContents* web_contents)
    : RenderFrameSubmissionObserver(
          RenderFrameMetadataProviderFromWebContents(web_contents)) {}

RenderFrameSubmissionObserver::~RenderFrameSubmissionObserver() {
  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::Vector2dF& 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(
    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();
  }
}

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_(render_widget_host),
      predicate_(predicate),
      event_received_(false) {
  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() {
  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(
    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 { owner_->RemoveObserver(this); }

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

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

 private:
  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) : owner_(owner) {
    owner->AddObserver(this);
  }
  ~FrameTreeNodeObserverImpl() override = default;

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

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

  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();
}

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

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

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

  DCHECK_EQ(desired_state_, NavigationState::WILL_START);
  WaitForDesiredState();
}

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

void TestNavigationManager::ResumeNavigation() {
  TRACE_EVENT("test", "TestNavigationManager::ResumeNavigation");
  DCHECK(current_state_ == NavigationState::STARTED ||
         current_state_ == NavigationState::RESPONSE);
  DCHECK_EQ(current_state_, desired_state_);
  DCHECK(navigation_paused_);
  ResumeIfPaused();
}

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

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

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

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

  was_prerendered_page_activation_ = handle->IsPrerenderedPageActivation();

  request_ = NavigationRequest::From(handle);
  if (request_->IsPageActivation()) {
    // For activating navigations, we have no way of stopping at
    // WillStartRequest since we don't run throttles. Callers should use
    // WaitForResponse() or WaitForFirstYieldAfterDidStartNavigation().
    DCHECK_NE(desired_state_, NavigationState::STARTED);

    // For prerendered page activation, CommitDeferringConditions has already
    // been run before starting navigation. Don't run them again.
    if (!request_->IsPrerenderedPageActivation()) {
      auto condition = std::make_unique<MockCommitDeferringCondition>(
          /*is_ready_to_commit=*/false,
          base::BindOnce(
              &TestNavigationManager::OnRunningCommitDeferringConditions,
              weak_factory_.GetWeakPtr()));
      request_->RegisterCommitDeferringConditionForTesting(
          std::move(condition));
    }
  } else {
    auto throttle = std::make_unique<TestNavigationManagerThrottle>(
        request_,
        base::BindOnce(&TestNavigationManager::OnWillStartRequest,
                       weak_factory_.GetWeakPtr()),
        base::BindOnce(&TestNavigationManager::OnWillProcessResponse,
                       weak_factory_.GetWeakPtr()));
    request_->RegisterThrottleForTesting(std::move(throttle));
  }

  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::STARTED;
  }
}

void TestNavigationManager::DidFinishNavigation(NavigationHandle* handle) {
  if (handle != request_)
    return;
  was_committed_ = handle->HasCommitted();
  was_successful_ = was_committed_ && !handle->IsErrorPage();
  DCHECK_EQ(was_prerendered_page_activation_.value(),
            request_->IsPrerenderedPageActivation());
  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::STARTED;
  navigation_paused_ = true;
  OnNavigationStateChanged();
}

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

void TestNavigationManager::OnRunningCommitDeferringConditions(
    base::OnceClosure resume_closure) {
  current_state_ = NavigationState::RESPONSE;
  commit_deferring_condition_resume_closure_ = std::move(resume_closure);
  navigation_paused_ = true;
  OnNavigationStateChanged();
}

// 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(!quit_closure_);
    base::RunLoop run_loop(message_loop_type_);
    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 (request_ && request_->IsPageActivation()) {
    DCHECK_NE(desired_state_, NavigationState::STARTED)
        << "Cannot use WaitForRequestStart() when managing an activating "
           "navigation. Use either WaitForFirstYieldAfterDidStartNavigation() "
           "or WaitForResponse()";
  }
  // If the state the user was waiting for has been reached, exit the message
  // loop.
  if (current_state_ >= desired_state_) {
    if (quit_closure_)
      std::move(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;

  if (!request_->IsPageActivation())
    request_->GetNavigationThrottleRunnerForTesting()->CallResumeForTesting();
  else if (commit_deferring_condition_resume_closure_)
    std::move(commit_deferring_condition_resume_closure_).Run();
}

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_);
}

NavigationHandleCommitObserver::NavigationHandleCommitObserver(
    content::WebContents* web_contents,
    const GURL& url)
    : WebContentsObserver(web_contents),
      url_(url),
      has_committed_(false),
      was_same_document_(false),
      was_renderer_initiated_(false) {}

void NavigationHandleCommitObserver::DidFinishNavigation(
    content::NavigationHandle* handle) {
  if (handle->GetURL() != url_)
    return;
  has_committed_ = true;
  was_same_document_ = handle->IsSameDocument();
  was_renderer_initiated_ = handle->IsRendererInitiated();
}

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

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

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 absl::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));
  run_loop_.Quit();
}

namespace {
mojo::Remote<blink::mojom::FileSystemManager> GetFileSystemManager(
    RenderProcessHost* rph) {
  FileSystemManagerImpl* file_system = static_cast<RenderProcessHostImpl*>(rph)
                                           ->GetFileSystemManagerForTesting();
  mojo::Remote<blink::mojom::FileSystemManager> file_system_manager_remote;
  // TODO(https://crbug.com/1243348): Pipe in the proper third-party StorageKey
  // value for the LegacyFileSystem; replace the empty construction below.
  GetIOThreadTaskRunner({})->PostTask(
      FROM_HERE,
      base::BindOnce(&FileSystemManagerImpl::BindReceiver,
                     base::Unretained(file_system), blink::StorageKey(),
                     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) {
  TestFileapiOperationWaiter waiter;
  mojo::Remote<blink::mojom::FileSystemManager> file_system_manager =
      GetFileSystemManager(process);
  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) {
  TestFileapiOperationWaiter waiter;
  mojo::Remote<blink::mojom::FileSystemManager> file_system_manager =
      GetFileSystemManager(process);
  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, 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:
  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();
  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)

ContextMenuInterceptor::ContextMenuInterceptor(
    content::RenderFrameHost* render_frame_host,
    ShowBehavior behavior)
    : render_frame_host_impl_(
          static_cast<RenderFrameHostImpl*>(render_frame_host)),
      run_loop_(std::make_unique<base::RunLoop>()),
      quit_closure_(run_loop_->QuitClosure()),
      show_behavior_(behavior) {
  impl_ = render_frame_host_impl_->local_frame_host_receiver_for_testing()
              .SwapImplForTesting(this);
}

ContextMenuInterceptor::~ContextMenuInterceptor() {
  render_frame_host_impl_->local_frame_host_receiver_for_testing()
      .SwapImplForTesting(impl_);
}

void ContextMenuInterceptor::Wait() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  run_loop_->Run();
  run_loop_ = nullptr;
}

void ContextMenuInterceptor::Reset() {
  ASSERT_EQ(run_loop_, nullptr);
  run_loop_ = std::make_unique<base::RunLoop>();
  quit_closure_ = run_loop_->QuitClosure();
}

blink::mojom::LocalFrameHost* ContextMenuInterceptor::GetForwardingInterface() {
  return impl_;
}

void ContextMenuInterceptor::ShowContextMenu(
    mojo::PendingAssociatedRemote<blink::mojom::ContextMenuClient>
        context_menu_client,
    const blink::UntrustworthyContextMenuParams& params) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  last_params_ = params;
  std::move(quit_closure_).Run();

  if (show_behavior_ == ShowBehavior::kPreventShow)
    return;

  GetForwardingInterface()->ShowContextMenu(std::move(context_menu_client),
                                            params);
}

UpdateUserActivationStateInterceptor::UpdateUserActivationStateInterceptor(
    content::RenderFrameHost* render_frame_host)
    : render_frame_host_impl_(
          static_cast<RenderFrameHostImpl*>(render_frame_host)) {
  impl_ = render_frame_host_impl_->local_frame_host_receiver_for_testing()
              .SwapImplForTesting(this);
}

UpdateUserActivationStateInterceptor::~UpdateUserActivationStateInterceptor() {
  render_frame_host_impl_->local_frame_host_receiver_for_testing()
      .SwapImplForTesting(impl_);
}

void UpdateUserActivationStateInterceptor::set_quit_handler(
    base::OnceClosure handler) {
  quit_handler_ = std::move(handler);
}

blink::mojom::LocalFrameHost*
UpdateUserActivationStateInterceptor::GetForwardingInterface() {
  return impl_;
}

void UpdateUserActivationStateInterceptor::UpdateUserActivationState(
    blink::mojom::UserActivationUpdateType update_type,
    blink::mojom::UserActivationNotificationType notification_type) {
  update_user_activation_state_ = true;
  if (quit_handler_)
    std::move(quit_handler_).Run();
  GetForwardingInterface()->UpdateUserActivationState(update_type,
                                                      notification_type);
}

WebContents* GetEmbedderForGuest(content::WebContents* guest) {
  CHECK(guest);
  return static_cast<WebContentsImpl*>(guest)->GetOuterWebContents();
}

namespace {

int LoadBasicRequest(
    network::mojom::URLLoaderFactory* url_loader_factory,
    const GURL& url,
    int load_flags,
    const absl::optional<url::Origin>& request_initiator = absl::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.GetCallback());
  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_corb_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->ForEachStoragePartition(
      base::BindRepeating([](StoragePartition* partition) {
        base::RunLoop run_loop;
        partition->GetCookieManagerForBrowserProcess()->FlushCookieStore(
            run_loop.QuitClosure());
        run_loop.Run();
      }));
}

bool TestGuestAutoresize(WebContents* embedder_web_contents,
                         WebContents* guest_web_contents) {
  FrameTreeNode* guest_main_frame_node =
      static_cast<WebContentsImpl*>(guest_web_contents)->GetFrameTree()->root();
  RenderFrameProxyHost* subframe_proxy_host =
      guest_main_frame_node->render_manager()->GetProxyToOuterDelegate();

  RenderWidgetHost* guest_rwh =
      guest_web_contents->GetRenderWidgetHostView()->GetRenderWidgetHost();
  RenderWidgetHostImpl* guest_rwh_impl =
      static_cast<RenderWidgetHostImpl*>(guest_rwh);

  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());
}

SynchronizeVisualPropertiesInterceptor::SynchronizeVisualPropertiesInterceptor(
    RenderFrameProxyHost* render_frame_proxy_host)
    : render_frame_proxy_host_(render_frame_proxy_host),
      screen_space_rect_run_loop_(std::make_unique<base::RunLoop>()) {
  impl_ = render_frame_proxy_host_->frame_host_receiver_for_testing()
              .SwapImplForTesting(this);
}

SynchronizeVisualPropertiesInterceptor::
    ~SynchronizeVisualPropertiesInterceptor() {
  render_frame_proxy_host_->frame_host_receiver_for_testing()
      .SwapImplForTesting(impl_);
}

blink::mojom::RemoteFrameHost*
SynchronizeVisualPropertiesInterceptor::GetForwardingInterface() {
  return render_frame_proxy_host_;
}

void SynchronizeVisualPropertiesInterceptor::WaitForRect() {
  screen_space_rect_run_loop_->Run();
}

void SynchronizeVisualPropertiesInterceptor::ResetRectRunLoop() {
  last_rect_ = gfx::Rect();
  screen_space_rect_run_loop_ = std::make_unique<base::RunLoop>();
  screen_space_rect_received_ = false;
}

viz::LocalSurfaceId SynchronizeVisualPropertiesInterceptor::WaitForSurfaceId() {
  surface_id_run_loop_ = std::make_unique<base::RunLoop>();
  surface_id_run_loop_->Run();
  return last_surface_id_;
}

void SynchronizeVisualPropertiesInterceptor::SynchronizeVisualProperties(
    const blink::FrameVisualProperties& visual_properties) {
  // Monitor |is_pinch_gesture_active| to determine when pinch gestures begin
  // and end.
  if (visual_properties.is_pinch_gesture_active &&
      !last_pinch_gesture_active_) {
    pinch_gesture_active_set_ = true;
  }
  if (!visual_properties.is_pinch_gesture_active &&
      last_pinch_gesture_active_) {
    pinch_gesture_active_cleared_ = true;
    if (pinch_end_run_loop_)
      pinch_end_run_loop_->Quit();
  }
  last_pinch_gesture_active_ = visual_properties.is_pinch_gesture_active;

  gfx::Rect screen_space_rect_in_dip = visual_properties.screen_space_rect;
  if (IsUseZoomForDSFEnabled()) {
    const float dsf =
        visual_properties.screen_infos.current().device_scale_factor;
    screen_space_rect_in_dip =
        gfx::Rect(gfx::ScaleToFlooredPoint(
                      visual_properties.screen_space_rect.origin(), 1.f / dsf),
                  gfx::ScaleToCeiledSize(
                      visual_properties.screen_space_rect.size(), 1.f / dsf));
  }
  // Track each rect updates.
  GetUIThreadTaskRunner({})->PostTask(
      FROM_HERE,
      base::BindOnce(
          &SynchronizeVisualPropertiesInterceptor::OnUpdatedFrameRectOnUI,
          weak_factory_.GetWeakPtr(), screen_space_rect_in_dip));

  // Track each surface id update.
  GetUIThreadTaskRunner({})->PostTask(
      FROM_HERE,
      base::BindOnce(
          &SynchronizeVisualPropertiesInterceptor::OnUpdatedSurfaceIdOnUI,
          weak_factory_.GetWeakPtr(), visual_properties.local_surface_id));

  // We can't nest on the IO thread. So tests will wait on the UI thread, so
  // post there to exit the nesting.
  GetUIThreadTaskRunner({})->PostTask(
      FROM_HERE,
      base::BindOnce(
          &SynchronizeVisualPropertiesInterceptor::OnUpdatedFrameSinkIdOnUI,
          weak_factory_.GetWeakPtr()));

  GetForwardingInterface()->SynchronizeVisualProperties(visual_properties);
}

void SynchronizeVisualPropertiesInterceptor::OnUpdatedFrameRectOnUI(
    const gfx::Rect& rect) {
  last_rect_ = rect;
  if (!screen_space_rect_received_) {
    screen_space_rect_received_ = true;
    // Tests looking at the rect currently expect all received input to finish
    // processing before the test continutes.
    screen_space_rect_run_loop_->QuitWhenIdle();
  }
}

void SynchronizeVisualPropertiesInterceptor::OnUpdatedFrameSinkIdOnUI() {
  run_loop_.Quit();
}

void SynchronizeVisualPropertiesInterceptor::OnUpdatedSurfaceIdOnUI(
    viz::LocalSurfaceId surface_id) {
  last_surface_id_ = surface_id;
  if (surface_id_run_loop_) {
    surface_id_run_loop_->QuitWhenIdle();
  }
}

void SynchronizeVisualPropertiesInterceptor::WaitForPinchGestureEnd() {
  if (pinch_gesture_active_cleared_)
    return;
  DCHECK(!pinch_end_run_loop_);
  pinch_end_run_loop_ = std::make_unique<base::RunLoop>();
  pinch_end_run_loop_->Run();
}

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->GetMainFrame()->InsertVisualStateCallback(
        base::BindLambdaForTesting([&](bool visual_state_updated) {
          ASSERT_TRUE(visual_state_updated);
          run_loop.Quit();
        }));
    run_loop.Run();
  }

  auto* rwh = RenderWidgetHostImpl::From(
      web_contents->GetMainFrame()->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 SkBitmap& 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);
}

}  // namespace content
