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

#include <stddef.h>

#include <cstddef>
#include <memory>
#include <string_view>
#include <utility>

#include "base/base64.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/json/json_reader.h"
#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "base/strings/safe_sprintf.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/system/sys_info.h"
#include "base/task/sequenced_task_runner.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_future.h"
#include "base/test/values_test_util.h"
#include "base/values.h"
#include "build/build_config.h"
#include "components/download/public/common/download_file_factory.h"
#include "components/download/public/common/download_file_impl.h"
#include "components/download/public/common/download_task_runner.h"
#include "components/services/storage/shared_storage/shared_storage_manager.h"
#include "content/browser/devtools/protocol/browser_handler.h"
#include "content/browser/devtools/protocol/devtools_download_manager_delegate.h"
#include "content/browser/devtools/protocol/devtools_protocol_test_support.h"
#include "content/browser/devtools/protocol/system_info.h"
#include "content/browser/devtools/render_frame_devtools_agent_host.h"
#include "content/browser/download/download_manager_impl.h"
#include "content/browser/host_zoom_map_impl.h"
#include "content/browser/preloading/prerender/prerender_final_status.h"
#include "content/browser/renderer_host/navigator.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_manager.h"
#include "content/public/browser/javascript_dialog_manager.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/ssl_status.h"
#include "content/public/browser/tracing_controller.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/back_forward_cache_util.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/download_test_observer.h"
#include "content/public/test/no_renderer_crashes_assertion.h"
#include "content/public/test/prerender_test_util.h"
#include "content/public/test/slow_download_http_response.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/shell/browser/shell_browser_context.h"
#include "content/shell/browser/shell_content_browser_client.h"
#include "content/shell/browser/shell_download_manager_delegate.h"
#include "content/test/content_browser_test_utils_internal.h"
#include "net/base/features.h"
#include "net/dns/dns_test_util.h"
#include "net/dns/mock_host_resolver.h"
#include "net/dns/public/secure_dns_mode.h"
#include "net/dns/public/util.h"
#include "net/test/ssl_test_util.h"
#include "net/test/test_doh_server.h"
#include "services/network/public/cpp/features.h"
#include "services/tracing/public/cpp/perfetto/perfetto_config.h"
#include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h"
#include "services/tracing/public/cpp/tracing_features.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/blink/public/common/chrome_debug_urls.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/page/page_zoom.h"
#include "third_party/boringssl/src/include/openssl/nid.h"
#include "third_party/boringssl/src/include/openssl/ssl.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/compositor/compositor_switches.h"
#include "ui/display/screen.h"
#include "ui/gfx/codec/jpeg_codec.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/geometry/skia_conversions.h"
#include "ui/snapshot/snapshot.h"
#include "url/origin.h"

#if BUILDFLAG(IS_POSIX)
#include "base/task/deferred_sequenced_task_runner.h"
#include "base/tracing/perfetto_task_runner.h"
#include "services/tracing/perfetto/system_test_utils.h"
#endif

#define EXPECT_SIZE_EQ(expected, actual)               \
  do {                                                 \
    EXPECT_EQ((expected).width(), (actual).width());   \
    EXPECT_EQ((expected).height(), (actual).height()); \
  } while (false)

using testing::ElementsAre;
using testing::Eq;
using testing::Pointee;

namespace content {

namespace {

const int kBudgetAllowed = 12;

class TestJavaScriptDialogManager : public JavaScriptDialogManager,
                                    public WebContentsDelegate {
 public:
  TestJavaScriptDialogManager() {}

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

  ~TestJavaScriptDialogManager() override {}

  void Handle() {
    if (!callback_.is_null()) {
      std::move(callback_).Run(true, std::u16string());
    } else {
      handle_ = true;
    }
  }

  // WebContentsDelegate
  JavaScriptDialogManager* GetJavaScriptDialogManager(
      WebContents* source) override {
    return this;
  }

  // JavaScriptDialogManager
  void RunJavaScriptDialog(WebContents* web_contents,
                           RenderFrameHost* render_frame_host,
                           JavaScriptDialogType dialog_type,
                           const std::u16string& message_text,
                           const std::u16string& default_prompt_text,
                           DialogClosedCallback callback,
                           bool* did_suppress_message) override {
    if (handle_) {
      handle_ = false;
      std::move(callback).Run(true, std::u16string());
    } else {
      callback_ = std::move(callback);
    }
  }

  void RunBeforeUnloadDialog(WebContents* web_contents,
                             RenderFrameHost* render_frame_host,
                             bool is_reload,
                             DialogClosedCallback callback) override {}

  bool HandleJavaScriptDialog(WebContents* web_contents,
                              bool accept,
                              const std::u16string* prompt_override) override {
    is_handled_ = true;
    return true;
  }

  void CancelDialogs(WebContents* web_contents,
                     bool reset_state) override {}

  bool is_handled() { return is_handled_; }

 private:
  DialogClosedCallback callback_;
  bool handle_ = false;
  bool is_handled_ = false;
};

}  // namespace

class SitePerProcessDevToolsProtocolTest : public DevToolsProtocolTest {
 public:
  void SetUpCommandLine(base::CommandLine* command_line) override {
    DevToolsProtocolTest::SetUpCommandLine(command_line);
    IsolateAllSitesForTesting(command_line);
  }
};

class SyntheticKeyEventTest : public DevToolsProtocolTest {
 protected:
  void SendKeyEvent(const std::string& type,
                    int modifier,
                    int windowsKeyCode,
                    int nativeKeyCode,
                    const std::string& key,
                    bool wait) {
    base::Value::Dict params;
    params.Set("type", type);
    params.Set("modifiers", modifier);
    params.Set("windowsVirtualKeyCode", windowsKeyCode);
    params.Set("nativeVirtualKeyCode", nativeKeyCode);
    params.Set("key", key);
    SendCommand("Input.dispatchKeyEvent", std::move(params), wait);
  }
};

class PrerenderDevToolsProtocolTest : public DevToolsProtocolTest {
 public:
  PrerenderDevToolsProtocolTest() {
    prerender_helper_ = std::make_unique<test::PrerenderTestHelper>(
        base::BindRepeating(&PrerenderDevToolsProtocolTest::web_contents,
                            base::Unretained(this)));
  }

  GURL GetUrl(const std::string& path) {
    return embedded_test_server()->GetURL("a.test", path);
  }

  bool HasHostForUrl(const GURL& url) {
    FrameTreeNodeId host_id = prerender_helper_->GetHostForUrl(url);
    return !!host_id;
  }

  FrameTreeNodeId AddPrerender(const GURL& prerendering_url) {
    return prerender_helper_->AddPrerender(prerendering_url);
  }

  RenderFrameHostImpl* GetPrerenderedMainFrameHost(FrameTreeNodeId host_id) {
    return static_cast<RenderFrameHostImpl*>(
        prerender_helper_->GetPrerenderedMainFrameHost(host_id));
  }

  void NavigatePrimaryPage(const GURL& url) {
    prerender_helper_->NavigatePrimaryPage(url);
  }

  // WebContentsDelegate overrides.
  PreloadingEligibility IsPrerender2Supported(
      WebContents& web_contents,
      PreloadingTriggerType trigger_type) override {
    return PreloadingEligibility::kEligible;
  }

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

  std::string AttachToTabTargetAndGetSessionId() {
    AttachToTabTarget(shell()->web_contents());
    shell()->web_contents()->SetDelegate(this);

    {
      base::Value::Dict params;
      params.Set("discover", true);
      SendCommandSync("Target.setDiscoverTargets", std::move(params));
    }

    std::string frame_target_id;
    for (int targetCount = 1; true; targetCount++) {
      base::Value::Dict result;
      result = WaitForNotification("Target.targetCreated", true);
      if (*result.FindStringByDottedPath("targetInfo.type") == "page") {
        frame_target_id =
            std::string(*result.FindStringByDottedPath("targetInfo.targetId"));
        break;
      }
      CHECK_LT(targetCount, 2);
    }

    {
      base::Value::Dict params;
      params.Set("targetId", frame_target_id);
      params.Set("flatten", true);
      const base::Value::Dict* result =
          SendCommandSync("Target.attachToTarget", std::move(params));
      CHECK(result);
      std::string session_id(*result->FindString("sessionId"));
      CHECK(session_id != "");
      return session_id;
    }
  }

 private:
  std::unique_ptr<test::PrerenderTestHelper> prerender_helper_;
};

class SyntheticMouseEventTest : public DevToolsProtocolTest {
 protected:
  void SendMouseEvent(const std::string& type,
                      int x,
                      int y,
                      const std::string& button,
                      bool wait) {
    base::Value::Dict params;
    params.Set("type", type);
    params.Set("x", x);
    params.Set("y", y);
    if (!button.empty()) {
      params.Set("button", button);
      params.Set("clickCount", 1);
    }
    SendCommand("Input.dispatchMouseEvent", std::move(params), wait);
  }

  void InitMouseDownLog() {
    ASSERT_TRUE(
        content::ExecJs(shell()->web_contents(),
                        "logs = []; window.addEventListener('mousedown', e => "
                        "logs.push(`${e.type},${e.clientX},${e.clientY}`));"));
  }

  std::string GetMouseDownLog() {
    return content::EvalJs(shell()->web_contents(), "window.logs.join(';')")
        .ExtractString();
  }

 private:
  base::test::ScopedFeatureList feature_list_;
};

IN_PROC_BROWSER_TEST_F(SyntheticKeyEventTest, KeyEventSynthesizeKey) {
  NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
  Attach();
  ASSERT_TRUE(content::ExecJs(
      shell()->web_contents(),
      "function handleKeyEvent(event) {"
      "domAutomationController.send(event.key);"
      "}"
      "document.body.addEventListener('keydown', handleKeyEvent);"
      "document.body.addEventListener('keyup', handleKeyEvent);"));

  DOMMessageQueue dom_message_queue(shell()->web_contents());

  // Send enter (keycode 13).
  SendKeyEvent("rawKeyDown", 0, 13, 13, "Enter", true);
  SendKeyEvent("keyUp", 0, 13, 13, "Enter", true);

  std::string key;
  ASSERT_TRUE(dom_message_queue.WaitForMessage(&key));
  EXPECT_EQ("\"Enter\"", key);
  ASSERT_TRUE(dom_message_queue.WaitForMessage(&key));
  EXPECT_EQ("\"Enter\"", key);

  // Send escape (keycode 27).
  SendKeyEvent("rawKeyDown", 0, 27, 27, "Escape", true);
  SendKeyEvent("keyUp", 0, 27, 27, "Escape", true);

  ASSERT_TRUE(dom_message_queue.WaitForMessage(&key));
  EXPECT_EQ("\"Escape\"", key);
  ASSERT_TRUE(dom_message_queue.WaitForMessage(&key));
  EXPECT_EQ("\"Escape\"", key);
}

// Flaky: https://crbug.com/889878
IN_PROC_BROWSER_TEST_F(SyntheticKeyEventTest, DISABLED_KeyboardEventAck) {
  NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
  Attach();
  ASSERT_TRUE(content::ExecJs(
      shell()->web_contents(),
      "document.body.addEventListener('keydown', () => {debugger;});"));

  auto filter = std::make_unique<InputMsgWatcher>(
      RenderWidgetHostImpl::From(shell()
                                     ->web_contents()
                                     ->GetPrimaryMainFrame()
                                     ->GetRenderViewHost()
                                     ->GetWidget()),
      blink::WebInputEvent::Type::kRawKeyDown);

  SendCommandSync("Debugger.enable");
  SendKeyEvent("rawKeyDown", 0, 13, 13, "Enter", false);

  // We expect that the debugger message event arrives *before* the input
  // event ack, and the subsequent command response for Input.dispatchKeyEvent.
  WaitForNotification("Debugger.paused");
  EXPECT_FALSE(filter->HasReceivedAck());
  EXPECT_EQ(1, received_responses_count());

  SendCommandSync("Debugger.resume");
  filter->WaitForAck();
  EXPECT_EQ(3, received_responses_count());
}

// Flaky: https://crbug.com/1263461
IN_PROC_BROWSER_TEST_F(SyntheticMouseEventTest, DISABLED_MouseEventAck) {
  NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
  Attach();
  ASSERT_TRUE(content::ExecJs(
      shell()->web_contents(),
      "document.body.addEventListener('mousedown', () => {debugger;});"));

  auto filter = std::make_unique<InputMsgWatcher>(
      RenderWidgetHostImpl::From(shell()
                                     ->web_contents()
                                     ->GetPrimaryMainFrame()
                                     ->GetRenderViewHost()
                                     ->GetWidget()),
      blink::WebInputEvent::Type::kMouseDown);

  SendCommandSync("Debugger.enable");
  SendMouseEvent("mousePressed", 15, 15, "left", false);

  // We expect that the debugger message event arrives *before* the input
  // event ack, and the subsequent command response for
  // Input.dispatchMouseEvent.
  WaitForNotification("Debugger.paused");
  EXPECT_FALSE(filter->HasReceivedAck());
  EXPECT_EQ(1, received_responses_count());

  SendCommandSync("Debugger.resume");
  filter->WaitForAck();
  EXPECT_EQ(3, received_responses_count());
}

IN_PROC_BROWSER_TEST_F(SyntheticMouseEventTest, MouseEventCoordinates) {
  ASSERT_TRUE(embedded_test_server()->Start());
  GURL test_url = embedded_test_server()->GetURL("/devtools/zoom.html");
  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1);
  Attach();
  InitMouseDownLog();
  // In about 1 out of 1000 runs, the event gets lost on the way to the
  // renderer. We repeat the event dispatch until it succeeds since we want to
  // test event coordinates.
  while (GetMouseDownLog() == "") {
    SendMouseEvent("mousePressed", 15, 15, "left", true);
  }
  ASSERT_EQ("mousedown,15,15", GetMouseDownLog());
}

IN_PROC_BROWSER_TEST_F(SyntheticMouseEventTest, MouseEventCoordinatesWithZoom) {
  ASSERT_TRUE(embedded_test_server()->Start());
  GURL test_url = embedded_test_server()->GetURL("/devtools/zoom.html");
  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1);
  Attach();
  SendCommandSync("Page.enable");
  InitMouseDownLog();

  HostZoomMap* host_zoom_map =
      HostZoomMap::GetForWebContents(shell()->web_contents());
  host_zoom_map->SetZoomLevelForHost(test_url.host(),
                                     blink::ZoomFactorToZoomLevel(2.5));
  WaitForNotification("Page.frameResized", true);

  // In about 1 out of 1000 runs, the event gets lost on the way to the
  // renderer. We repeat the event dispatch until it succeeds since we want to
  // test event coordinates.
  while (GetMouseDownLog() == "") {
    SendMouseEvent("mousePressed", 15, 15, "left", true);
  }
  ASSERT_EQ("mousedown,15,15", GetMouseDownLog());
}

namespace {
SkBitmap DecodePNG(std::string_view base64_data) {
  std::optional<std::vector<uint8_t>> data = base::Base64Decode(base64_data);
  SkBitmap bitmap = gfx::PNGCodec::Decode(data.value());
  CHECK(!bitmap.isNull());
  return bitmap;
}

SkBitmap DecodeJPEG(std::string_view base64_data) {
  std::optional<std::vector<uint8_t>> data = base::Base64Decode(base64_data);
  SkBitmap bitmap = gfx::JPEGCodec::Decode(data.value());
  CHECK(!bitmap.isNull());
  return bitmap;
}

int ColorsSquareDiff(SkColor color1, SkColor color2) {
  auto a_diff = static_cast<int>(SkColorGetA(color1)) -
                static_cast<int>(SkColorGetA(color2));
  auto r_diff = static_cast<int>(SkColorGetR(color1)) -
                static_cast<int>(SkColorGetR(color2));
  auto g_diff = static_cast<int>(SkColorGetG(color1)) -
                static_cast<int>(SkColorGetG(color2));
  auto b_diff = static_cast<int>(SkColorGetB(color1)) -
                static_cast<int>(SkColorGetB(color2));
  return a_diff * a_diff + r_diff * r_diff + g_diff * g_diff +
             b_diff * b_diff;
}

bool ColorsMatchWithinLimit(SkColor color1, SkColor color2, int max_collor_diff) {
  return ColorsSquareDiff(color1, color2) <= max_collor_diff * max_collor_diff;
}

// Adapted from cc::ExactPixelComparator.
bool MatchesBitmap(const SkBitmap& expected_bmp,
                   const SkBitmap& actual_bmp,
                   const gfx::Rect& matching_mask,
                   float device_scale_factor,
                   int max_collor_diff) {
  // Number of pixels with an error
  int error_pixels_count = 0;

  gfx::Rect error_bounding_rect = gfx::Rect();

  // Scale expectations along with the mask.
  device_scale_factor = device_scale_factor ? device_scale_factor : 1;

  DCHECK(gfx::SkIRectToRect(actual_bmp.bounds()).Contains(matching_mask));

  for (int x = matching_mask.x(); x < matching_mask.right(); ++x) {
    for (int y = matching_mask.y(); y < matching_mask.bottom(); ++y) {
      if (x * device_scale_factor >= actual_bmp.width() ||
          y * device_scale_factor >= actual_bmp.height() ||
          x >= expected_bmp.width() || y >= expected_bmp.height()) {
        continue;
      }

      SkColor actual_color =
          actual_bmp.getColor(x * device_scale_factor, y * device_scale_factor);
      SkColor expected_color = expected_bmp.getColor(x, y);
      if (!ColorsMatchWithinLimit(actual_color, expected_color, max_collor_diff)) {
        if (error_pixels_count < 10) {
          LOG(ERROR) << "Pixel (" << x << "," << y
                     << "). Expected: " << std::hex << expected_color
                     << ", actual: " << actual_color << std::dec
                     << ", square diff: " << ColorsSquareDiff(expected_color, actual_color);
        }
        error_pixels_count++;
        error_bounding_rect.Union(gfx::Rect(x, y, 1, 1));
      }
    }
  }

  if (error_pixels_count != 0) {
    LOG(ERROR) << "Number of pixel with an error: " << error_pixels_count;
    LOG(ERROR) << "Error Bounding Box : " << error_bounding_rect.ToString();
    return false;
  }

  return true;
}
}  // namespace

enum class ScreenshotEncoding { PNG, JPEG, WEBP };

std::string EncodingEnumToString(ScreenshotEncoding encoding) {
  switch (encoding) {
    case ScreenshotEncoding::PNG:
      return "png";
    case ScreenshotEncoding::JPEG:
      return "jpeg";
    case ScreenshotEncoding::WEBP:
      return "webp";
    default:
      return "";
  }
}

class CaptureScreenshotTest : public DevToolsProtocolTest {
 protected:
  SkBitmap CaptureScreenshot(ScreenshotEncoding encoding,
                             bool from_surface,
                             const gfx::RectF& clip = gfx::RectF(),
                             float clip_scale = 0,
                             bool capture_beyond_viewport = false,
                             bool expect_error = false) {
    base::Value::Dict params;
    params.Set("format", EncodingEnumToString(encoding));
    params.Set("quality", 100);
    params.Set("fromSurface", from_surface);
    if (capture_beyond_viewport) {
      params.Set("captureBeyondViewport", true);
    }
    if (clip_scale) {
      base::Value::Dict clip_value;
      clip_value.Set("x", clip.x());
      clip_value.Set("y", clip.y());
      clip_value.Set("width", clip.width());
      clip_value.Set("height", clip.height());
      clip_value.Set("scale", clip_scale);
      params.Set("clip", std::move(clip_value));
    }
    SendCommandSync("Page.captureScreenshot", std::move(params));

    if (expect_error && error()) {
      EXPECT_THAT(error()->FindInt("code"),
                  testing::Optional(
                      static_cast<int>(crdtp::DispatchCode::SERVER_ERROR)));
    } else {
      const std::string* base64 = result()->FindString("data");
      if (encoding == ScreenshotEncoding::PNG) {
        return DecodePNG(*base64);
      } else if (encoding == ScreenshotEncoding::JPEG) {
        return DecodeJPEG(*base64);
      } else {
        // Decode not implemented.
      }
    }
    return SkBitmap();
  }

  void CaptureScreenshotAndCompareTo(const SkBitmap& expected_bitmap,
                                     ScreenshotEncoding encoding,
                                     bool from_surface,
                                     float device_scale_factor = 0,
                                     const gfx::RectF& clip = gfx::RectF(),
                                     float clip_scale = 0,
                                     bool capture_beyond_viewport = false) {
    SkBitmap result_bitmap = CaptureScreenshot(
        encoding, from_surface, clip, clip_scale, capture_beyond_viewport);

    gfx::Rect matching_mask(gfx::SkIRectToRect(expected_bitmap.bounds()));
#if BUILDFLAG(IS_MAC)
    // Mask out the corners, which may be drawn differently on Mac because of
    // rounded corners.
    matching_mask.Inset(4);
#endif

    // A color profile can be installed on the host that could affect
    // pixel colors. Also JPEG compression could further distort the color.
    // Allow some error between actual and expected pixel values.
    // That assumes there is no shift in pixel positions, so it only works
    // reliably if all pixels have equal values.
    int max_collor_diff = 20;

    EXPECT_TRUE(MatchesBitmap(expected_bitmap, result_bitmap, matching_mask,
                              device_scale_factor, max_collor_diff));
  }

  gfx::Size GetPageContentSize() {
    const base::Value::Dict* content_size =
        SendCommandSync("Page.getLayoutMetrics")->FindDict("cssContentSize");
    return gfx::Size(content_size->FindInt("width").value(),
                     content_size->FindInt("height").value());
  }

  // We compare against the actual physical backing size rather than the
  // view size, because the view size is stored adjusted for DPI and only in
  // integer precision.
  gfx::Size GetViewSize() {
    return static_cast<RenderWidgetHostViewBase*>(
               shell()->web_contents()->GetRenderWidgetHostView())
        ->GetCompositorViewportPixelSize();
  }

  // We compare the bitmap with the captured screenshot to verify the
  // size and color of the screenshot.
  SkBitmap GenerateBitmap(gfx::Size size, SkColor color) {
    SkBitmap expected_bitmap;
    expected_bitmap.allocN32Pixels(size.width(), size.height());
    expected_bitmap.eraseColor(color);
    return expected_bitmap;
  }

  void SetDefaultBackgroundColorOverride(int r, int g, int b, float a) {
    auto params = base::Value::Dict();
    base::Value::Dict color;
    color.Set("r", r);
    color.Set("g", g);
    color.Set("b", b);
    color.Set("a", a);
    params.Set("color", std::move(color));
    SendCommandSync("Emulation.setDefaultBackgroundColorOverride",
                    std::move(params));
  }

  void SetDeviceMetricsOverride(int width,
                                int height,
                                float device_scale_factor,
                                bool mobile,
                                std::optional<bool> fitWindow) {
    auto params = base::Value::Dict();
    params.Set("width", width);
    params.Set("height", height);
    params.Set("deviceScaleFactor", device_scale_factor);
    params.Set("mobile", mobile);
    if (fitWindow.has_value()) {
      params.Set("fitWindow", fitWindow.value());
    }
    SendCommandSync("Emulation.setDeviceMetricsOverride", std::move(params));
  }

  // Takes a screenshot of a colored box that is positioned inside the frame.
  void PlaceAndCaptureBox(const gfx::Size& frame_size,
                          const gfx::Size& box_size,
                          float screenshot_scale,
                          float device_scale_factor) {
    static const int kBoxOffsetHeight = 100;
    const gfx::Size scaled_box_size =
        ScaleToFlooredSize(box_size, screenshot_scale);
    base::Value::Dict params;

    VLOG(1) << "Testing screenshot of box with size " << box_size.width() << "x"
            << box_size.height() << "px at scale " << screenshot_scale
            << " ...";

    // Draw a blue box of provided size in the horizontal center of the page.
    EXPECT_TRUE(content::ExecJs(
        shell()->web_contents(),
        base::StringPrintf(
            "var style = document.body.style;                             "
            "style.overflow = 'hidden';                                   "
            "style.minHeight = '%dpx';                                    "
            "style.backgroundImage = 'linear-gradient(#0000ff, #0000ff)'; "
            "style.backgroundSize = '%dpx %dpx';                          "
            "style.backgroundPosition = '50%% %dpx';                      "
            "style.backgroundRepeat = 'no-repeat';                        ",
            box_size.height() + kBoxOffsetHeight, box_size.width(),
            box_size.height(), kBoxOffsetHeight)));

    // Force frame size: The offset of the blue box within the frame shouldn't
    // change during screenshotting. This verifies that the page doesn't observe
    // a change in frame size as a side effect of screenshotting.
    SetDeviceMetricsOverride(frame_size.width(), frame_size.height(),
                             device_scale_factor, false, std::nullopt);

    // Resize frame to scaled blue box size.
    gfx::RectF clip;
    clip.set_width(box_size.width());
    clip.set_height(box_size.height());
    clip.set_x((frame_size.width() - box_size.width()) / 2.);
    clip.set_y(kBoxOffsetHeight);

    // Capture screenshot and verify that it is indeed blue.
    SkBitmap expected_bitmap =
        GenerateBitmap(scaled_box_size, SkColorSetRGB(0x00, 0x00, 0xff));

    // If the device scale factor is 0,
    // get the original device scale factor to compare with
    if (!device_scale_factor) {
      device_scale_factor =
          display::Screen::Get()->GetPrimaryDisplay().device_scale_factor();
    }

    CaptureScreenshotAndCompareTo(expected_bitmap, ScreenshotEncoding::PNG,
                                  /*from_surface=*/true, device_scale_factor,
                                  clip, screenshot_scale);

    // Reset for next screenshot.
    SendCommandSync("Emulation.clearDeviceMetricsOverride");
  }

  bool IsTrusted() override { return is_trusted_; }

  bool is_trusted_ = true;

 private:
#if !BUILDFLAG(IS_ANDROID)
  void SetUp() override {
    EnablePixelOutput();
    DevToolsProtocolTest::SetUp();
  }
#endif
};

IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest,
                       CaptureScreenshotBeyondViewport_OutOfView) {
  // TODO(crbug.com/40488022) This test fails consistently on low-end Android
  // devices.
  if (base::SysInfo::IsLowEndDevice())
    return;

  // Load dummy page before getting the view size.
  shell()->LoadURL(GURL("data:text/html,"));
  gfx::Size view_size = GetViewSize();

  // Make a page a bit bigger than the view to force scrollbars to be shown.
  shell()->LoadURL(
      GURL(base::StringPrintf("data:text/html,"
                              R"(<body style='background:%%23123456;height:%dpx;
                         width:%dpx'></body>)",
                              /*content_height*/ view_size.height() + 10,
                              /*content_width*/ view_size.width() + 10)));

  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
  Attach();

  // Generate expected screenshot without any scrollbars.
  gfx::Size actual_page_size = GetPageContentSize();
  SkBitmap expected_bitmap =
      GenerateBitmap(actual_page_size, SkColorSetRGB(0x12, 0x34, 0x56));

  float device_scale_factor =
      display::Screen::Get()->GetPrimaryDisplay().device_scale_factor();

  // Verify there are no scrollbars on the screenshot.
  CaptureScreenshotAndCompareTo(
      expected_bitmap, ScreenshotEncoding::PNG, /*from_surface=*/true,
      device_scale_factor,
      /*clip=*/
      gfx::RectF(0, 0, actual_page_size.width(), actual_page_size.height()),
      /*clip_scale=*/1, /*capture_beyond_viewport=*/true);
  CaptureScreenshotAndCompareTo(expected_bitmap, ScreenshotEncoding::PNG,
                                /*from_surface=*/true, device_scale_factor,
                                /*clip=*/gfx::RectF(), /*clip_scale=*/0,
                                /*capture_beyond_viewport=*/true);
}

IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest,
                       CaptureScreenshotBeyondViewport_IFrame) {
  // TODO(crbug.com/40488022) This test fails consistently on low-end Android
  // devices.
  if (base::SysInfo::IsLowEndDevice())
    return;

  // Load dummy page before getting the view size.
  shell()->LoadURL(GURL("data:text/html,"));
  gfx::Size view_size = GetViewSize();

  // Make a page a bit bigger than the view to force scrollbars to be shown.
  int content_height = view_size.height() + 50;
  int content_width = view_size.width() + 50;
  int margin = 100;
  shell()->LoadURL(
      GURL(base::StringPrintf("data:text/html,"
                              R"(
            <body style=' height:%dpx;
                          width:%dpx;'>
            <iframe style=" height:%dpx;
                            width:%dpx;
                            background:%%23123456;
                            border:none;">
            </iframe></body>
          )",
                              content_height + margin, content_width + margin,
                              content_height, content_width)));

  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
  Attach();

  // Generate expected screenshot without any scrollbars.
  SkBitmap expected_bitmap =
      GenerateBitmap(gfx::Size(content_width, content_height),
                     SkColorSetRGB(0x12, 0x34, 0x56));

  float device_scale_factor =
      display::Screen::Get()->GetPrimaryDisplay().device_scale_factor();

  // Verify there are no scrollbars on the screenshot.
  // Even if margin is 0 then the iframe appears 8px away from beginning of the
  // page
  CaptureScreenshotAndCompareTo(
      expected_bitmap, ScreenshotEncoding::PNG, /*from_surface=*/true,
      device_scale_factor,
      /*clip=*/gfx::RectF(8, 8, content_width, content_height),
      /*clip_scale=*/1, /*capture_beyond_viewport=*/true);
}

// ChromeOS and Android has fading out scrollbars, which makes the test flacky.
// TODO(crbug.com/40157725) Android has a problem with changing scale.
// TODO(crbug.com/40156819) Android Lollipop has a problem with capturing
// screenshot.
// TODO(crbug.com/40815512): Failing on MacOS.
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_MAC)
#define MAYBE_CaptureScreenshotBeyondViewport_InnerScrollbarsAreShown \
  DISABLED_CaptureScreenshotBeyondViewport_InnerScrollbarsAreShown
#else
#define MAYBE_CaptureScreenshotBeyondViewport_InnerScrollbarsAreShown \
  CaptureScreenshotBeyondViewport_InnerScrollbarsAreShown
#endif
IN_PROC_BROWSER_TEST_F(
    CaptureScreenshotTest,
    MAYBE_CaptureScreenshotBeyondViewport_InnerScrollbarsAreShown) {
  // TODO(crbug.com/40488022) This test fails consistently on low-end Android
  // devices.
  if (base::SysInfo::IsLowEndDevice())
    return;

  shell()->LoadURL(GURL(
      "data:text/html,<body><div style='width: 50px; height: 50px; overflow: "
      "scroll;'><h3>test</h3><h3>test</h3><h3>test</h3></div></body>"));

  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
  Attach();

  gfx::Size view_size = GetViewSize();

  // Capture a screenshot not "from surface", meaning without emulation and
  // without changing preferences, as-is.
  SkBitmap expected_bitmap =
      CaptureScreenshot(ScreenshotEncoding::PNG, /*from_surface=*/false);

  float device_scale_factor =
      display::Screen::Get()->GetPrimaryDisplay().device_scale_factor();

  // Compare the captured screenshot with one made "from_surface", where actual
  // scrollbar magic happened, and verify it looks the same, meaning the
  // internal scrollbars are rendered.
  CaptureScreenshotAndCompareTo(
      expected_bitmap, ScreenshotEncoding::PNG, /*from_surface=*/true,
      device_scale_factor,
      /*clip=*/gfx::RectF(0, 0, view_size.width(), view_size.height()),
      /*clip_scale=*/1, /*capture_beyond_viewport=*/true);
}

// ChromeOS and Android don't support software compositing.
#if !BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_ANDROID)

class NoGPUCaptureScreenshotTest : public CaptureScreenshotTest {
  void SetUpCommandLine(base::CommandLine* command_line) override {
    CaptureScreenshotTest::SetUpCommandLine(command_line);
    command_line->AppendSwitch(switches::kDisableGpuCompositing);
  }
};

// Tests that large screenshots are composited fine with software compositor.
// Regression test for https://crbug.com/1137291.
// Flaky on Linux.  http://crbug.com/1301176
// TODO(crbug.com/396301195): Failing on Win 10 Tests x64 dbg bot.
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN)
#define MAYBE_LargeScreenshot DISABLED_LargeScreenshot
#else
#define MAYBE_LargeScreenshot LargeScreenshot
#endif
IN_PROC_BROWSER_TEST_F(NoGPUCaptureScreenshotTest, MAYBE_LargeScreenshot) {
  // This test fails consistently on low-end Android devices.
  // See crbug.com/653637.
  // TODO(eseckler): Reenable with error limit if necessary.
  if (base::SysInfo::IsLowEndDevice())
    return;
  // If disabling software compositing is disabled by the test caller,
  // we're out of luck.
  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kDisableSoftwareCompositingFallback)) {
    return;
  }
  shell()->LoadURL(
      GURL("data:text/html,"
           "<style>body,html { padding: 0; margin: 0; }</style>"
           "<div style='width: 1250px; height: 8440px; "
           "     background: linear-gradient(red, blue)'></div>"));
  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
  Attach();

  SetDeviceMetricsOverride(/*width=*/1280, /*height=*/8440,
                           /*device_scale_factor=*/1,
                           /*mobile=*/false,
                           /*fitWindow=*/std::nullopt);
  auto bitmap = CaptureScreenshot(ScreenshotEncoding::PNG, true,
                                  gfx::RectF(0, 0, 1280, 8440), 1);
  SendCommandSync("Emulation.clearDeviceMetricsOverride");

  EXPECT_EQ(1280, bitmap.width());
  EXPECT_EQ(8440, bitmap.height());

  // Top-left is red-ish.
  SkColor top_left = bitmap.getColor(0, 0);
  EXPECT_GT(static_cast<int>(SkColorGetR(top_left)), 128);
  EXPECT_LT(static_cast<int>(SkColorGetB(top_left)), 128);

  // Bottom-left is blue-ish.
  SkColor bottom_left = bitmap.getColor(0, 8339);
  EXPECT_LT(static_cast<int>(SkColorGetR(bottom_left)), 128);
  EXPECT_GT(static_cast<int>(SkColorGetB(bottom_left)), 128);
}

#endif  // !BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_ANDROID)

// Setting frame size (through RWHV) is not supported on Android.
// This test seems to be very flaky on all platforms: https://crbug.com/801173
IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest, DISABLED_CaptureScreenshotArea) {
  static const gfx::Size kFrameSize(800, 600);

  shell()->LoadURL(GURL("about:blank"));
  Attach();

  // Test capturing a subarea inside the emulated frame at different scales.
  PlaceAndCaptureBox(kFrameSize, gfx::Size(100, 200), 1.0, 1.);
  PlaceAndCaptureBox(kFrameSize, gfx::Size(100, 200), 2.0, 1.);
  PlaceAndCaptureBox(kFrameSize, gfx::Size(100, 200), 0.5, 1.);

  // Check non-1 device scale factor.
  PlaceAndCaptureBox(kFrameSize, gfx::Size(100, 200), 1.0, 2.);
  // Ensure not emulating device scale factor works.
  PlaceAndCaptureBox(kFrameSize, gfx::Size(100, 200), 1.0, 0.);
}

// Verifies that setDefaultBackgroundColorOverride changes the background color
// of a page that does not specify one.
IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest,
                       SetDefaultBackgroundColorOverride) {
  if (base::SysInfo::IsLowEndDevice())
    return;

  shell()->LoadURL(GURL("about:blank"));
  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
  Attach();

  SetDefaultBackgroundColorOverride(/*r=*/0x00, /*g=*/0x00, /*b=*/0xff,
                                    /*a=*/1.0);

  gfx::Size view_size = GetViewSize();
  SkBitmap expected_bitmap =
      GenerateBitmap(view_size, SkColorSetRGB(0x00, 0x00, 0xff));
  CaptureScreenshotAndCompareTo(expected_bitmap, ScreenshotEncoding::PNG,
                                /*from_surface=*/true);

  // Tests that resetting Emulation.setDefaultBackgroundColorOverride
  // clears the background color override.
  SendCommandSync("Emulation.setDefaultBackgroundColorOverride");
  expected_bitmap.eraseColor(SK_ColorWHITE);
  CaptureScreenshotAndCompareTo(expected_bitmap, ScreenshotEncoding::PNG,
                                /*from_surface=*/true);
}

// Bellow tests verify that setDefaultBackgroundColor and captureScreenshot
// support a fully and semi-transparent background,
// and that setDeviceMetricsOverride doesn't affect it.
IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest,
// TODO(crbug.com/40875549): Fix this failing test
#if BUILDFLAG(IS_ANDROID)
                       DISABLED_TransparentScreenshotsViewport) {
#else
                       TransparentScreenshotsViewport) {
#endif
  if (base::SysInfo::IsLowEndDevice())
    return;

  shell()->LoadURL(
      GURL("data:text/html,<body style='background:transparent'></body>"));
  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
  Attach();

  SetDefaultBackgroundColorOverride(/*r=*/0, /*g=*/0, /*b=*/0, /*a=*/0);

  gfx::Size view_size = GetViewSize();
  SkBitmap expected_viewport_bitmap =
      GenerateBitmap(view_size, SK_ColorTRANSPARENT);

  CaptureScreenshotAndCompareTo(expected_viewport_bitmap,
                                ScreenshotEncoding::PNG,
                                /*from_surface=*/true);

#if !BUILDFLAG(IS_ANDROID)

  float device_scale_factor =
      display::Screen::Get()->GetPrimaryDisplay().device_scale_factor();

  // Check that device emulation does not affect the transparency.
  SetDeviceMetricsOverride(view_size.width(), view_size.height(),
                           /*device_scale_factor=*/0,
                           /*mobile=*/false,
                           /*fitWindow=*/false);
  CaptureScreenshotAndCompareTo(expected_viewport_bitmap,
                                ScreenshotEncoding::PNG,
                                /*from_surface=*/true, device_scale_factor);

  SendCommandSync("Emulation.clearDeviceMetricsOverride");
#endif  // !BUILDFLAG(IS_ANDROID)

  SetDefaultBackgroundColorOverride(/*r=*/255, /*g=*/0, /*b=*/0,
                                    /*a=*/1.0 / 255 * 16);

  expected_viewport_bitmap.eraseColor(SkColorSetARGB(16, 255, 0, 0));

  CaptureScreenshotAndCompareTo(expected_viewport_bitmap,
                                ScreenshotEncoding::PNG,
                                /*from_surface=*/true);

#if !BUILDFLAG(IS_ANDROID)
  // Check that device emulation does not affect the transparency.

  SetDeviceMetricsOverride(view_size.width(), view_size.height(),
                           /*device_scale_factor=*/0, /*mobile=*/false,
                           /*fitWindow=*/false);

  CaptureScreenshotAndCompareTo(expected_viewport_bitmap,
                                ScreenshotEncoding::PNG,
                                /*from_surface=*/true, device_scale_factor);

  SendCommandSync("Emulation.clearDeviceMetricsOverride");
#endif  // !BUILDFLAG(IS_ANDROID)
}

IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest,
// TODO(crbug.com/40875549): Fix this failing test
#if BUILDFLAG(IS_ANDROID)
                       DISABLED_TransparentScreenshotsBeyondViewport) {
#else
                       TransparentScreenshotsBeyondViewport) {
#endif
  if (base::SysInfo::IsLowEndDevice())
    return;

  shell()->LoadURL(
      GURL("data:text/html,<body style='background:transparent'></body>"));
  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
  Attach();

  SetDefaultBackgroundColorOverride(/*r=*/0, /*g=*/0, /*b=*/0, /*a=*/0);

  gfx::Size view_size = GetViewSize();

  // When capturing full page screenshots, the page content size can differ
  // from the defined dimensions. Therefore, we need to check for the actual
  // layout metrics of the page and compare that with our result.
  SkBitmap expected_full_page_bitmap =
      GenerateBitmap(GetPageContentSize(), SK_ColorTRANSPARENT);
  SkBitmap expected_clip_bitmap =
      GenerateBitmap(view_size, SK_ColorTRANSPARENT);

  float device_scale_factor =
      display::Screen::Get()->GetPrimaryDisplay().device_scale_factor();
  gfx::RectF clip;
  clip.SetRect(0, 0, view_size.width(), view_size.height());

  // checks for beyond_viewport
  CaptureScreenshotAndCompareTo(expected_clip_bitmap, ScreenshotEncoding::PNG,
                                /*from_surface=*/true, device_scale_factor,
                                clip, /*clip_scale=*/1,
                                /*capture_beyond_viewport=*/true);
  CaptureScreenshotAndCompareTo(expected_full_page_bitmap,
                                ScreenshotEncoding::PNG,
                                /*from_surface=*/true, device_scale_factor,
                                /*clip=*/gfx::RectF(), /*clip_scale=*/0,
                                /*capture_beyond_viewport=*/true);

#if !BUILDFLAG(IS_ANDROID)

  // Check that device emulation does not affect the transparency.
  SetDeviceMetricsOverride(view_size.width(), view_size.height(),
                           /*device_scale_factor=*/0,
                           /*mobile=*/false,
                           /*fitWindow=*/false);

  // checks for beyond_viewport
  CaptureScreenshotAndCompareTo(expected_clip_bitmap, ScreenshotEncoding::PNG,
                                /*from_surface=*/true, device_scale_factor,
                                clip,
                                /*clip_scale=*/1,
                                /*capture_beyond_viewport=*/true);

  CaptureScreenshotAndCompareTo(expected_full_page_bitmap,
                                ScreenshotEncoding::PNG,
                                /*from_surface=*/true, device_scale_factor,
                                /*clip=*/gfx::RectF(), /*clip_scale=*/0,
                                /*capture_beyond_viewport=*/true);

  SendCommandSync("Emulation.clearDeviceMetricsOverride");
#endif  // !BUILDFLAG(IS_ANDROID)

  SetDefaultBackgroundColorOverride(/*r=*/255, /*g=*/0, /*b=*/0,
                                    /*a=*/1.0 / 255 * 16);

  // When capturing full page screenshots, the page content size can differ
  // from the defined dimensions. Therefore, we need to check for the actual
  // layout metrics of the page and compare that with our result.
  expected_full_page_bitmap =
      GenerateBitmap(GetPageContentSize(), SkColorSetARGB(16, 255, 0, 0));

  expected_clip_bitmap =
      GenerateBitmap(view_size, SkColorSetARGB(16, 255, 0, 0));

  // Check for beyond-viewport
  CaptureScreenshotAndCompareTo(expected_clip_bitmap, ScreenshotEncoding::PNG,
                                /*from_surface=*/true, device_scale_factor,
                                clip,
                                /*clip_scale=*/1,
                                /*capture_beyond_viewport=*/true);

  CaptureScreenshotAndCompareTo(expected_full_page_bitmap,
                                ScreenshotEncoding::PNG,
                                /*from_surface=*/true, device_scale_factor,
                                /*clip=*/gfx::RectF(), /*clip_scale=*/0,
                                /*capture_beyond_viewport=*/true);

#if !BUILDFLAG(IS_ANDROID)
  // Check that device emulation does not affect the transparency.

  SetDeviceMetricsOverride(view_size.width(), view_size.height(),
                           /*device_scale_factor=*/0, /*mobile=*/false,
                           /*fitWindow=*/false);

  // Checks for beyond_viewport
  CaptureScreenshotAndCompareTo(expected_clip_bitmap, ScreenshotEncoding::PNG,
                                /*from_surface=*/true, device_scale_factor,
                                /*clip=*/clip,
                                /*clip_scale=*/1,
                                /*capture_beyond_viewport=*/true);

  CaptureScreenshotAndCompareTo(expected_full_page_bitmap,
                                ScreenshotEncoding::PNG,
                                /*from_surface=*/true, device_scale_factor,
                                /*clip=*/gfx::RectF(), /*clip_scale=*/0,
                                /*capture_beyond_viewport=*/true);

  SendCommandSync("Emulation.clearDeviceMetricsOverride");
#endif  // !BUILDFLAG(IS_ANDROID)
}

// TODO(crbug.com/40239673): Semi-transparent screenshots of viewport fail on
// android devices - a scrollbar is showing.
#if !BUILDFLAG(IS_ANDROID)
IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest, TransparentScreenshotsFull) {
  if (base::SysInfo::IsLowEndDevice())
    return;

  shell()->LoadURL(
      GURL("data:text/html,<body style='background:transparent'></body>"));
  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
  Attach();

  SetDefaultBackgroundColorOverride(/*r=*/0, /*g=*/0, /*b=*/0, /*a=*/0);

  gfx::Size view_size = GetViewSize();
  SkBitmap expected_viewport_bitmap =
      GenerateBitmap(view_size, SK_ColorTRANSPARENT);

  CaptureScreenshotAndCompareTo(expected_viewport_bitmap,
                                ScreenshotEncoding::PNG,
                                /*from_surface=*/true);  //.

  float device_scale_factor =
      display::Screen::Get()->GetPrimaryDisplay().device_scale_factor();
  gfx::RectF clip;
  clip.SetRect(0, 0, view_size.width(), view_size.height());

  // checks for beyond_viewport
  CaptureScreenshotAndCompareTo(
      expected_viewport_bitmap, ScreenshotEncoding::PNG,
      /*from_surface=*/true, device_scale_factor, clip, /*clip_scale=*/1,
      /*capture_beyond_viewport=*/true);

  // When capturing full page screenshots, the page content size can differ
  // from the defined dimensions. Therefore, we need to check for the actual
  // layout metrics of the page and compare that with our result.
  SkBitmap expected_full_page_bitmap =
      GenerateBitmap(GetPageContentSize(), SK_ColorTRANSPARENT);

  CaptureScreenshotAndCompareTo(expected_full_page_bitmap,
                                ScreenshotEncoding::PNG,
                                /*from_surface=*/true, device_scale_factor,
                                /*clip=*/gfx::RectF(), /*clip_scale=*/0,
                                /*capture_beyond_viewport=*/true);

  // Check that device emulation does not affect the transparency.
  SetDeviceMetricsOverride(view_size.width(), view_size.height(),
                           /*device_scale_factor=*/0,
                           /*mobile=*/false,
                           /*fitWindow=*/false);

  CaptureScreenshotAndCompareTo(expected_viewport_bitmap,
                                ScreenshotEncoding::PNG,
                                /*from_surface=*/true, device_scale_factor);

  // checks for beyond_viewport
  CaptureScreenshotAndCompareTo(
      expected_viewport_bitmap, ScreenshotEncoding::PNG,
      /*from_surface=*/true, device_scale_factor, clip,
      /*clip_scale=*/1,
      /*capture_beyond_viewport=*/true);

  CaptureScreenshotAndCompareTo(expected_full_page_bitmap,
                                ScreenshotEncoding::PNG,
                                /*from_surface=*/true, device_scale_factor,
                                /*clip=*/gfx::RectF(), /*clip_scale=*/0,
                                /*capture_beyond_viewport=*/true);

  SendCommandSync("Emulation.clearDeviceMetricsOverride");

  SetDefaultBackgroundColorOverride(/*r=*/255, /*g=*/0, /*b=*/0,
                                    /*a=*/1.0 / 255 * 16);

  expected_viewport_bitmap.eraseColor(SkColorSetARGB(16, 255, 0, 0));

  CaptureScreenshotAndCompareTo(expected_viewport_bitmap,
                                ScreenshotEncoding::PNG,
                                /*from_surface=*/true);

  // Check for beyond-viewport
  CaptureScreenshotAndCompareTo(
      expected_viewport_bitmap, ScreenshotEncoding::PNG,
      /*from_surface=*/true, device_scale_factor, clip,
      /*clip_scale=*/1,
      /*capture_beyond_viewport=*/true);

  // When capturing full page screenshots, the page content size can differ
  // from the defined dimensions. Therefore, we need to check for the actual
  // layout metrics of the page and compare that with our result.
  expected_full_page_bitmap =
      GenerateBitmap(GetPageContentSize(), SkColorSetARGB(16, 255, 0, 0));

  CaptureScreenshotAndCompareTo(expected_full_page_bitmap,
                                ScreenshotEncoding::PNG,
                                /*from_surface=*/true, device_scale_factor,
                                /*clip=*/gfx::RectF(), /*clip_scale=*/0,
                                /*capture_beyond_viewport=*/true);

  // Check that device emulation does not affect the transparency.

  SetDeviceMetricsOverride(view_size.width(), view_size.height(),
                           /*device_scale_factor=*/0, /*mobile=*/false,
                           /*fitWindow=*/false);

  CaptureScreenshotAndCompareTo(expected_viewport_bitmap,
                                ScreenshotEncoding::PNG,
                                /*from_surface=*/true, device_scale_factor);

  // Checks for beyond_viewport
  CaptureScreenshotAndCompareTo(expected_viewport_bitmap,
                                ScreenshotEncoding::PNG,
                                /*from_surface=*/true, device_scale_factor,
                                /*clip=*/clip,
                                /*clip_scale=*/1,
                                /*capture_beyond_viewport=*/true);

  CaptureScreenshotAndCompareTo(expected_full_page_bitmap,
                                ScreenshotEncoding::PNG,
                                /*from_surface=*/true, device_scale_factor,
                                /*clip=*/gfx::RectF(), /*clip_scale=*/0,
                                /*capture_beyond_viewport=*/true);

  SendCommandSync("Emulation.clearDeviceMetricsOverride");
}
#endif  // !BUILDFLAG(IS_ANDROID)

#if !BUILDFLAG(IS_ANDROID)
// Verifies that CaptureScreenshotsBeyondViewport supports emulation with the
// use of setDeviceMetricsOverride and setDefaultBackgroundColorOverride
IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest,
                       CaptureScreenshotBeyondViewport_Emulation) {
  // TODO(crbug.com/40488022) This test fails consistently on low-end Android
  // devices.
  if (base::SysInfo::IsLowEndDevice())
    return;

  // Load dummy page before getting the view size.
  shell()->LoadURL(GURL("data:text/html,"));

  gfx::Size view_size = GetViewSize();

  // Make a page a bigger than the view to have fullpage behaviour.
  int content_height = view_size.height() + 100;
  int content_width = view_size.width() + 100;

  shell()->LoadURL(
      GURL(base::StringPrintf("data:text/html,"
                              R"(<body style='background:%%23123456;height:%dpx;
                              width:%dpx'></body>)",
                              content_height, content_width)));

  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
  Attach();

  SetDefaultBackgroundColorOverride(/*r=*/0x12, /*g=*/0x34, /*b=*/0x56,
                                    /*a=*/1.0);

  float device_scale_factor =
      display::Screen::Get()->GetPrimaryDisplay().device_scale_factor();

  // Check device emulation.
  // Additionally checks if emulation doesnt affect color change
  SetDeviceMetricsOverride(content_width, content_height,
                           /*device_scale_factor=*/0, /*mobile=*/false,
                           /*fitWindow=*/false);
  gfx::Size actual_page_size = GetPageContentSize();
  SkBitmap expected_bitmap =
      GenerateBitmap(actual_page_size, SkColorSetRGB(0x12, 0x34, 0x56));

  // Test for no Clip
  CaptureScreenshotAndCompareTo(
      expected_bitmap, ScreenshotEncoding::PNG,
      /*from_surface=*/true, device_scale_factor, /*clip=*/gfx::RectF(),
      /*clip_scale=*/0, /*capture_beyond_viewport=*/true);
  // Test for Clip
  CaptureScreenshotAndCompareTo(
      expected_bitmap, ScreenshotEncoding::PNG, /*from_surface=*/true,
      device_scale_factor,
      /*clip=*/
      gfx::RectF(0, 0, actual_page_size.width(), actual_page_size.height()),
      /*clip_scale=*/1, /*capture_beyond_viewport=*/true);
  SendCommandSync("Emulation.clearDeviceMetricsOverride");
}
#endif  // !BUILDFLAG(IS_ANDROID)

IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest,
                       OnlyScreenshotsFromSurfaceWhenUnsafeNotAllowed) {
  is_trusted_ = false;
  shell()->LoadURL(GURL("about:blank"));
  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
  Attach();

  CaptureScreenshot(ScreenshotEncoding::PNG, false, gfx::RectF(), 0, true,
                    true);
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest,
                       NoCrashDeviceMetricsOverrideAutoResize) {
  NavigateToURLBlockUntilNavigationsComplete(
      shell(), GURL("data:text/html,<body></body>"), 1);

  // Enable auto resize.
  gfx::Size min_size(10, 10);
  gfx::Size max_size(100, 100);

  RenderWidgetHostImpl* rwh = static_cast<RenderWidgetHostImpl*>(
      shell()->web_contents()->GetPrimaryMainFrame()->GetRenderWidgetHost());
  rwh->GetView()->EnableAutoResize(min_size, max_size);

  Attach();

  // Send command.
  auto params = base::Value::Dict();
  params.Set("width", 50);
  params.Set("height", 50);
  params.Set("deviceScaleFactor", 1);
  params.Set("mobile", false);
  ASSERT_FALSE(
      SendCommandSync("Emulation.setDeviceMetricsOverride", std::move(params)));

  // Should not crash and should return an error.
  EXPECT_EQ(*error()->FindInt("code"),
            static_cast<int>(crdtp::DispatchCode::SERVER_ERROR));
  EXPECT_EQ(*error()->FindString("message"),
            "Target does not support metrics override");
}

#if BUILDFLAG(IS_ANDROID)
// Disabled, see http://crbug.com/469947.
IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, DISABLED_SynthesizePinchGesture) {
  GURL test_url = GetTestUrl("devtools", "synthetic_gesture_tests.html");
  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1);
  Attach();

  int old_width = EvalJs(shell(), "window.innerWidth").ExtractInt();

  int old_height = EvalJs(shell(), "window.innerHeight").ExtractInt();

  base::Value::Dict params;
  params.Set("x", old_width / 2);
  params.Set("y", old_height / 2);
  params.Set("scaleFactor", 2.0);
  SendCommandSync("Input.synthesizePinchGesture", std::move(params));

  int new_width = EvalJs(shell(), "window.innerWidth").ExtractInt();
  ASSERT_DOUBLE_EQ(2.0, static_cast<double>(old_width) / new_width);

  int new_height = EvalJs(shell(), "window.innerHeight").ExtractInt();
  ASSERT_DOUBLE_EQ(2.0, static_cast<double>(old_height) / new_height);
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, DISABLED_SynthesizeScrollGesture) {
  GURL test_url = GetTestUrl("devtools", "synthetic_gesture_tests.html");
  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1);
  Attach();

  ASSERT_EQ(0, EvalJs(shell(), "document.body.scrollTop"));

  base::Value::Dict params;
  params.Set("x", 0);
  params.Set("y", 0);
  params.Set("xDistance", 0);
  params.Set("yDistance", -100);
  SendCommandSync("Input.synthesizeScrollGesture", std::move(params));

  ASSERT_EQ(100, EvalJs(shell(), "document.body.scrollTop"));
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, DISABLED_SynthesizeTapGesture) {
  GURL test_url = GetTestUrl("devtools", "synthetic_gesture_tests.html");
  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1);
  Attach();

  ASSERT_EQ(0, EvalJs(shell(), "document.body.scrollTop"));

  base::Value::Dict params;
  params.Set("x", 16);
  params.Set("y", 16);
  params.Set("gestureSourceType", "touch");
  SendCommandSync("Input.synthesizeTapGesture", std::move(params));

  // The link that we just tapped should take us to the bottom of the page. The
  // new value of |document.body.scrollTop| will depend on the screen dimensions
  // of the device that we're testing on, but in any case it should be greater
  // than 0.
  ASSERT_GT(EvalJs(shell(), "document.body.scrollTop").ExtractInt(), 0);
}
#endif  // BUILDFLAG(IS_ANDROID)

// TODO(crbug.com/40825729): Flaky on multiple bots.
IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, DISABLED_PageCrash) {
  ASSERT_TRUE(embedded_test_server()->Start());
  GURL test_url = embedded_test_server()->GetURL("/devtools/navigation.html");
  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1);
  Attach();

  base::Value::Dict command_params;
  command_params.Set("discover", true);
  SendCommandSync("Target.setDiscoverTargets", std::move(command_params));

  base::Value::Dict params = WaitForNotification("Target.targetCreated", true);
  EXPECT_THAT(*params.FindStringByDottedPath("targetInfo.type"), Eq("page"));
  std::string target_id = *params.FindStringByDottedPath("targetInfo.targetId");

  ClearNotifications();
  {
    content::ScopedAllowRendererCrashes scoped_allow_renderer_crashes;
    SendCommandAsync("Page.crash");
    params = WaitForNotification("Target.targetCrashed", true);
  }
  EXPECT_EQ(*params.FindString("targetId"), target_id);

  ClearNotifications();
  shell()->LoadURL(test_url);
  WaitForNotification("Inspector.targetReloadedAfterCrash", true);
}

#if BUILDFLAG(IS_ANDROID)
#define MAYBE_PageCrashInFrame DISABLED_PageCrashInFrame
#else
#define MAYBE_PageCrashInFrame PageCrashInFrame
#endif
IN_PROC_BROWSER_TEST_F(SitePerProcessDevToolsProtocolTest,
                       MAYBE_PageCrashInFrame) {
  ASSERT_TRUE(embedded_test_server()->Start());
  GURL test_url =
      embedded_test_server()->GetURL("/devtools/page-with-oopif.html");
  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1);
  Attach();

  base::Value::Dict command_params;
  command_params.Set("discover", true);
  SendCommandSync("Target.setDiscoverTargets", std::move(command_params));

  base::Value::Dict params;
  std::string frame_target_id;
  for (int targetCount = 1; true; targetCount++) {
    params = WaitForNotification("Target.targetCreated", true);
    if (*params.FindStringByDottedPath("targetInfo.type") == "iframe") {
      frame_target_id = *params.FindStringByDottedPath("targetInfo.targetId");
      break;
    }
    ASSERT_LT(targetCount, 2);
  }

  command_params = base::Value::Dict();
  command_params.Set("targetId", frame_target_id);
  command_params.Set("flatten", true);
  const base::Value::Dict* result =
      SendCommandSync("Target.attachToTarget", std::move(command_params));
  ASSERT_TRUE(result);
  const std::string* session_id = result->FindString("sessionId");
  ASSERT_TRUE(session_id);

  ClearNotifications();
  {
    content::ScopedAllowRendererCrashes scoped_allow_renderer_crashes;
    SendSessionCommand("Page.crash", base::Value::Dict(), *session_id, false);
    params = WaitForNotification("Target.targetCrashed", true);
  }
  EXPECT_EQ(frame_target_id, *params.FindString("targetId"));
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, PageCrashClearsPendingCommands) {
  ASSERT_TRUE(embedded_test_server()->Start());
  GURL test_url = embedded_test_server()->GetURL("/devtools/navigation.html");
  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1);
  Attach();

  base::Value::Dict command_params;
  command_params.Set("discover", true);

  SendCommandSync("Target.setDiscoverTargets", std::move(command_params));

  base::Value::Dict params = WaitForNotification("Target.targetCreated", true);
  EXPECT_THAT(*params.FindStringByDottedPath("targetInfo.type"), Eq("page"));
  std::string target_id = *params.FindStringByDottedPath("targetInfo.targetId");

  SendCommandSync("Debugger.enable");

  command_params = base::Value::Dict();
  command_params.Set("expression", "console.log('first page'); debugger");
  SendCommandAsync("Runtime.evaluate", std::move(command_params));
  WaitForNotification("Debugger.paused");

  {
    content::ScopedAllowRendererCrashes scoped_allow_renderer_crashes;
    shell()->LoadURL(GURL(blink::kChromeUICrashURL));
    params = WaitForNotification("Target.targetCrashed", true);
  }
  ClearNotifications();
  SendCommandAsync("Page.reload");
  WaitForNotification("Inspector.targetReloadedAfterCrash", true);
  command_params = base::Value::Dict();
  command_params.Set("expression", "console.log('second page')");
  SendCommandSync("Runtime.evaluate", std::move(command_params));
  EXPECT_THAT(console_messages_, ElementsAre("first page", "second page"));
}

// TODO(crbug.com/40811521): Disabled due to flakiness. Flaky on mac and linux
// la-cros
IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest,
                       DISABLED_NavigationPreservesMessages) {
  ASSERT_TRUE(embedded_test_server()->Start());
  GURL test_url = embedded_test_server()->GetURL("/devtools/navigation.html");
  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1);
  Attach();
  SendCommandAsync("Page.enable");

  base::Value::Dict params;
  test_url = GetTestUrl("devtools", "navigation.html");
  params.Set("url", test_url.spec());
  TestNavigationObserver navigation_observer(shell()->web_contents());
  SendCommandSync("Page.navigate", std::move(params));
  navigation_observer.Wait();

  EXPECT_GE(received_responses_count(), 2);
  EXPECT_TRUE(HasExistingNotification("Page.frameStartedLoading"));
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest,
                       NavigationToFileUrlRequiresFileAccess) {
  Attach();

  base::Value::Dict params;
  GURL test_url = GetTestUrl("devtools", "navigation.html");
  params.Set("url", test_url.spec());
  ASSERT_TRUE(SendCommandSync("Page.navigate", params.Clone()));

  Detach();
  SetMayReadLocalFiles(false);

  Attach();

  ASSERT_FALSE(SendCommandSync("Page.navigate", params.Clone()));
  EXPECT_THAT(
      error()->FindInt("code"),
      testing::Optional(static_cast<int>(crdtp::DispatchCode::SERVER_ERROR)));
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, CrossSiteNoDetach) {
  content::SetupCrossSiteRedirector(embedded_test_server());
  ASSERT_TRUE(embedded_test_server()->Start());

  GURL test_url1 = embedded_test_server()->GetURL(
      "A.com", "/devtools/navigation.html");
  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url1, 1);
  Attach();

  GURL test_url2 = embedded_test_server()->GetURL(
      "B.com", "/devtools/navigation.html");
  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url2, 1);

  EXPECT_FALSE(HasExistingNotification());
}

// TODO(crbug.com/40811670): Flaky on MacOS.
IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, DISABLED_CrossSiteNavigation) {
  content::SetupCrossSiteRedirector(embedded_test_server());
  ASSERT_TRUE(embedded_test_server()->Start());

  GURL test_url1 =
      embedded_test_server()->GetURL("A.com", "/devtools/navigation.html");
  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url1, 1);
  Attach();
  SendCommandAsync("Page.enable");

  GURL test_url2 =
      embedded_test_server()->GetURL("B.com", "/devtools/navigation.html");
  base::Value::Dict params;
  params.Set("url", test_url2.spec());
  const base::Value::Dict* result =
      SendCommandSync("Page.navigate", std::move(params));
  const std::string* frame_id = result->FindString("frameId");

  base::Value::Dict frame_stopped =
      WaitForNotification("Page.frameStoppedLoading", true);
  EXPECT_EQ(*frame_stopped.FindString("frameId"), *frame_id);
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, CrossSiteCrash) {
  set_agent_host_can_close();
  content::SetupCrossSiteRedirector(embedded_test_server());
  ASSERT_TRUE(embedded_test_server()->Start());

  GURL test_url1 =
      embedded_test_server()->GetURL("A.com", "/devtools/navigation.html");
  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url1, 1);
  Attach();
  CrashTab(shell()->web_contents());

  GURL test_url2 =
      embedded_test_server()->GetURL("B.com", "/devtools/navigation.html");
  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url2, 1);

  // Should not crash at this point.
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, InspectorTargetCrashedNavigate) {
  set_agent_host_can_close();
  ASSERT_TRUE(embedded_test_server()->Start());
  GURL url_a = embedded_test_server()->GetURL("a.com", "/title1.html");

  NavigateToURLBlockUntilNavigationsComplete(shell(), url_a, 1);
  Attach();
  SendCommandSync("Inspector.enable");

  {
    ScopedAllowRendererCrashes scoped_allow_renderer_crashes(shell());
    shell()->LoadURL(GURL(blink::kChromeUICrashURL));
    WaitForNotification("Inspector.targetCrashed");
  }

  ClearNotifications();
  shell()->LoadURL(url_a);
  WaitForNotification("Inspector.targetReloadedAfterCrash", true);
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, TargetGetTargetsAfterCrash) {
  set_agent_host_can_close();
  ASSERT_TRUE(embedded_test_server()->Start());
  GURL url_a = embedded_test_server()->GetURL("a.com", "/title1.html");

  NavigateToURLBlockUntilNavigationsComplete(shell(), url_a, 1);
  Attach();
  SendCommandSync("Inspector.enable");
  SendCommandSync("Target.getTargets");
  EXPECT_EQ(1u, result()->FindList("targetInfos")->size());

  {
    ScopedAllowRendererCrashes scoped_allow_renderer_crashes(shell());
    shell()->LoadURL(GURL(blink::kChromeUICrashURL));
    WaitForNotification("Inspector.targetCrashed");
  }

  SendCommandSync("Target.getTargets");
  EXPECT_EQ(1u, result()->FindList("targetInfos")->size());
}

// Same as in DevToolsProtocolTest.InspectorTargetCrashedNavigate, but with a
// cross-process navigation at the end.
// Regression test for https://crbug.com/990315
IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest,
                       InspectorTargetCrashedNavigateCrossProcess) {
  set_agent_host_can_close();
  ASSERT_TRUE(embedded_test_server()->Start());
  GURL url_a = embedded_test_server()->GetURL("a.com", "/title1.html");
  GURL url_b = embedded_test_server()->GetURL("b.com", "/title1.html");

  NavigateToURLBlockUntilNavigationsComplete(shell(), url_a, 1);
  Attach();
  SendCommandSync("Inspector.enable");

  {
    ScopedAllowRendererCrashes scoped_allow_renderer_crashes(shell());
    shell()->LoadURL(GURL(blink::kChromeUICrashURL));
    WaitForNotification("Inspector.targetCrashed");
  }

  ClearNotifications();
  shell()->LoadURL(url_b);
  WaitForNotification("Inspector.targetReloadedAfterCrash", true);
}

#if BUILDFLAG(IS_ANDROID)
#define MAYBE_InspectorTargetCrashedReload DISABLED_InspectorTargetCrashedReload
#else
#define MAYBE_InspectorTargetCrashedReload InspectorTargetCrashedReload
#endif
IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest,
                       MAYBE_InspectorTargetCrashedReload) {
  set_agent_host_can_close();
  GURL url = GURL("data:text/html,<body></body>");
  NavigateToURLBlockUntilNavigationsComplete(shell(), url, 1);
  Attach();
  SendCommandSync("Inspector.enable");

  {
    ScopedAllowRendererCrashes scoped_allow_renderer_crashes(shell());
    shell()->LoadURL(GURL(blink::kChromeUICrashURL));
    WaitForNotification("Inspector.targetCrashed");
  }

  ClearNotifications();
  SendCommandAsync("Page.reload");
  WaitForNotification("Inspector.targetReloadedAfterCrash", true);
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, ReconnectPreservesState) {
  ASSERT_TRUE(embedded_test_server()->Start());
  GURL test_url = embedded_test_server()->GetURL("/devtools/navigation.html");
  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1);

  Shell* second = CreateBrowser();
  NavigateToURLBlockUntilNavigationsComplete(second, test_url, 1);

  Attach();
  SendCommandSync("Runtime.enable");

  agent_host_->DisconnectWebContents();
  agent_host_->ConnectWebContents(second->web_contents());
  WaitForNotification("Runtime.executionContextsCleared");
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, CrossSitePauseInBeforeUnload) {
  content::SetupCrossSiteRedirector(embedded_test_server());
  ASSERT_TRUE(embedded_test_server()->Start());

  NavigateToURLBlockUntilNavigationsComplete(shell(),
      embedded_test_server()->GetURL("A.com", "/devtools/navigation.html"), 1);
  Attach();
  SendCommandSync("Debugger.enable");

  ASSERT_TRUE(content::ExecJs(
      shell(),
      "window.onbeforeunload = function() { debugger; return null; }"));

  shell()->LoadURL(
      embedded_test_server()->GetURL("B.com", "/devtools/navigation.html"));
  WaitForNotification("Debugger.paused");
  TestNavigationObserver observer(shell()->web_contents(), 1);
  SendCommandSync("Debugger.resume");
  observer.Wait();
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, InspectDuringFrameSwap) {
  content::SetupCrossSiteRedirector(embedded_test_server());
  ASSERT_TRUE(embedded_test_server()->Start());

  GURL test_url1 =
      embedded_test_server()->GetURL("A.com", "/devtools/navigation.html");
  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url1, 1);

  ShellAddedObserver new_shell_observer;
  EXPECT_TRUE(ExecJs(shell(), "window.open('about:blank','foo');"));
  Shell* new_shell = new_shell_observer.GetShell();
  EXPECT_TRUE(new_shell->web_contents()->HasOpener());

  agent_host_ = DevToolsAgentHost::GetOrCreateFor(new_shell->web_contents());
  agent_host_->AttachClient(this);

  GURL test_url2 =
      embedded_test_server()->GetURL("B.com", "/devtools/navigation.html");

  // After this navigation, if the bug exists, the process will crash.
  NavigateToURLBlockUntilNavigationsComplete(new_shell, test_url2, 1);

  // Ensure that the A.com process is still alive by executing a script in the
  // original tab.
  //
  // TODO(alexmos, nasko):  A better way to do this is to navigate the original
  // tab to another site, watch for process exit, and check whether there was a
  // crash. However, currently there's no way to wait for process exit
  // regardless of whether it's a crash or not.  RenderProcessHostWatcher
  // should be fixed to support waiting on both WATCH_FOR_PROCESS_EXIT and
  // WATCH_FOR_HOST_DESTRUCTION, and then used here.
  EXPECT_EQ(true, EvalJs(shell(), "!!window.open('', 'foo');"));

  GURL test_url3 =
      embedded_test_server()->GetURL("A.com", "/devtools/navigation.html");

  // After this navigation, if the bug exists, the process will crash.
  NavigateToURLBlockUntilNavigationsComplete(new_shell, test_url3, 1);

  // Ensure that the A.com process is still alive by executing a script in the
  // original tab.
  EXPECT_EQ(true, EvalJs(shell(), "!!window.open('', 'foo');"));
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, DoubleCrash) {
  set_agent_host_can_close();
  ASSERT_TRUE(embedded_test_server()->Start());
  GURL test_url = embedded_test_server()->GetURL("/devtools/navigation.html");
  NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
  Attach();
  SendCommandSync("ServiceWorker.enable");
  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1);
  CrashTab(shell()->web_contents());
  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1);
  CrashTab(shell()->web_contents());
  NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
  // Should not crash at this point.
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, ReloadBlankPage) {
  Shell* window =  Shell::CreateNewWindow(
      shell()->web_contents()->GetBrowserContext(),
      GURL("javascript:x=1"),
      nullptr,
      gfx::Size());
  WaitForLoadStop(window->web_contents());
  Attach();
  SendCommandAsync("Page.reload");
  // Should not crash at this point.
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, EvaluateInBlankPage) {
  NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
  Attach();
  base::Value::Dict params;
  params.Set("expression", "window");
  SendCommandSync("Runtime.evaluate", std::move(params));
  EXPECT_FALSE(result()->Find("exceptionDetails"));
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest,
    EvaluateInBlankPageAfterNavigation) {
  ASSERT_TRUE(embedded_test_server()->Start());
  GURL test_url = embedded_test_server()->GetURL("/devtools/navigation.html");
  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1);
  Attach();
  NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
  base::Value::Dict params;
  params.Set("expression", "window");
  SendCommandSync("Runtime.evaluate", std::move(params));
  EXPECT_FALSE(result()->Find("exceptionDetails"));
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, JavaScriptDialogNotifications) {
  NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
  Attach();
  TestJavaScriptDialogManager dialog_manager;
  WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
  wc->SetDelegate(&dialog_manager);
  SendCommandSync("Page.enable");

  base::Value::Dict params;
  params.Set("expression", "prompt('hello?', 'default')");
  SendCommandAsync("Runtime.evaluate", std::move(params));

  base::Value::Dict notification =
      WaitForNotification("Page.javascriptDialogOpening");
  EXPECT_EQ(*notification.FindString("url"), "about:blank");
  EXPECT_EQ(*notification.FindString("message"), "hello?");
  EXPECT_EQ(*notification.FindString("type"), "prompt");
  EXPECT_EQ(*notification.FindString("defaultPrompt"), "default");

  params = base::Value::Dict();
  params.Set("accept", true);
  params.Set("promptText", "hi!");
  SendCommandAsync("Page.handleJavaScriptDialog", std::move(params));

  notification = WaitForNotification("Page.javascriptDialogClosed", true);
  EXPECT_THAT(notification.FindBool("result"), testing::Optional(true));

  EXPECT_TRUE(dialog_manager.is_handled());

  EXPECT_THAT(*notification.FindString("userInput"), Eq("hi!"));
  wc->SetDelegate(nullptr);
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, JavaScriptDialogInterop) {
  NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
  Attach();
  TestJavaScriptDialogManager dialog_manager;
  WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
  wc->SetDelegate(&dialog_manager);
  SendCommandSync("Page.enable");
  SendCommandSync("Runtime.enable");

  base::Value::Dict params;
  params.Set("expression", "alert('42')");
  SendCommandAsync("Runtime.evaluate", std::move(params));
  WaitForNotification("Page.javascriptDialogOpening");

  dialog_manager.Handle();
  WaitForNotification("Page.javascriptDialogClosed", true);
  wc->SetDelegate(nullptr);
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, PageDisableWithOpenedDialog) {
  NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
  Attach();
  TestJavaScriptDialogManager dialog_manager;
  WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
  wc->SetDelegate(&dialog_manager);

  SendCommandSync("Page.enable");
  SendCommandSync("Runtime.enable");

  base::Value::Dict params;
  params.Set("expression", "alert('42')");
  SendCommandAsync("Runtime.evaluate", std::move(params));
  WaitForNotification("Page.javascriptDialogOpening");
  EXPECT_TRUE(wc->IsJavaScriptDialogShowing());

  EXPECT_FALSE(dialog_manager.is_handled());
  SendCommandAsync("Page.disable");
  EXPECT_TRUE(wc->IsJavaScriptDialogShowing());
  EXPECT_FALSE(dialog_manager.is_handled());
  dialog_manager.Handle();
  EXPECT_FALSE(wc->IsJavaScriptDialogShowing());

  params = base::Value::Dict();
  params.Set("expression", "42");
  SendCommandSync("Runtime.evaluate", std::move(params));

  wc->SetDelegate(nullptr);
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, PageDisableWithNoDialogManager) {
  NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
  Attach();
  WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
  wc->SetDelegate(nullptr);

  SendCommandSync("Page.enable");
  SendCommandSync("Runtime.enable");

  base::Value::Dict params;
  params.Set("expression", "alert('42');");
  SendCommandAsync("Runtime.evaluate", std::move(params));
  WaitForNotification("Page.javascriptDialogOpening");
  EXPECT_TRUE(wc->IsJavaScriptDialogShowing());

  SendCommandSync("Page.disable");
  EXPECT_FALSE(wc->IsJavaScriptDialogShowing());
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, BeforeUnloadDialog) {
  NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
  Attach();
  TestJavaScriptDialogManager dialog_manager;

  WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
  wc->SetDelegate(&dialog_manager);
  SendCommandSync("Runtime.enable");

  base::Value::Dict params;

  params = base::Value::Dict();
  params.Set("expression", "window.onbeforeunload=()=>{return 'prompt';}");
  params.Set("userGesture", true);
  SendCommandSync("Runtime.evaluate", std::move(params));

  SendCommandSync("Page.enable");
  SendCommandAsync("Page.reload");

  base::Value::Dict notification =
      WaitForNotification("Page.javascriptDialogOpening", true);

  EXPECT_THAT(*notification.FindString("url"), Eq("about:blank"));
  EXPECT_THAT(*notification.FindString("type"), Eq("beforeunload"));

  params = base::Value::Dict();
  params.Set("accept", true);
  SendCommandAsync("Page.handleJavaScriptDialog", std::move(params));
  WaitForNotification("Page.javascriptDialogClosed", true);
  wc->SetDelegate(nullptr);
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, BrowserCreateAndCloseTarget) {
  NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
  Attach();
  EXPECT_EQ(1u, shell()->windows().size());
  base::Value::Dict params;
  params.Set("url", "about:blank");
  SendCommandSync("Target.createTarget", std::move(params));
  const std::string* target_id = result()->FindString("targetId");
  ASSERT_TRUE(target_id);
  EXPECT_EQ(2u, shell()->windows().size());

  // TODO(eseckler): Since the `blink::WebView` is closed asynchronously, we
  // currently don't verify that the command actually closes the shell.
  params = base::Value::Dict();
  params.Set("targetId", *target_id);
  SendCommandSync("Target.closeTarget", std::move(params));

  EXPECT_THAT(result()->FindBool("success"), testing::Optional(true));
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, BrowserGetTargets) {
  NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
  Attach();
  SendCommandSync("Target.getTargets");
  const base::Value::List* target_infos = result()->FindList("targetInfos");
  ASSERT_TRUE(target_infos);
  EXPECT_EQ(1u, target_infos->size());
  const base::Value& target_info_value = target_infos->front();
  const base::Value::Dict* target_info = target_info_value.GetIfDict();
  ASSERT_TRUE(target_info);
  const std::string* target_id = target_info->FindString("target_id");
  const std::string* type = target_info->FindString("type");
  const std::string* title = target_info->FindString("title");
  const std::string* url = target_info->FindString("url");
  EXPECT_FALSE(target_id);
  ASSERT_TRUE(type);
  ASSERT_TRUE(title);
  ASSERT_TRUE(url);
  EXPECT_EQ("page", *type);
  EXPECT_EQ("about:blank", *title);
  EXPECT_EQ("about:blank", *url);
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, VirtualTimeTest) {
  NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
  Attach();

  base::Value::Dict params;
  params.Set("policy", "pause");
  SendCommandSync("Emulation.setVirtualTimePolicy", std::move(params));

  params = base::Value::Dict();
  params.Set("expression",
             "setTimeout(function(){console.log('before')}, 999);"
             "setTimeout(function(){console.log('at')}, 1000);"
             "setTimeout(function(){console.log('after')}, 1001);");
  SendCommandSync("Runtime.evaluate", std::move(params));

  // Let virtual time advance for one second.
  params = base::Value::Dict();
  params.Set("policy", "advance");
  params.Set("budget", 1000);
  SendCommandSync("Emulation.setVirtualTimePolicy", std::move(params));

  WaitForNotification("Emulation.virtualTimeBudgetExpired");

  params = base::Value::Dict();
  params.Set("expression", "console.log('done')");
  SendCommandSync("Runtime.evaluate", std::move(params));

  // The third timer should not fire.
  EXPECT_THAT(console_messages_, ElementsAre("before", "at", "done"));

  // Let virtual time advance for another second, which should make the third
  // timer fire.
  params = base::Value::Dict();
  params.Set("policy", "advance");
  params.Set("budget", 1000);
  SendCommandSync("Emulation.setVirtualTimePolicy", std::move(params));

  WaitForNotification("Emulation.virtualTimeBudgetExpired");

  EXPECT_THAT(console_messages_, ElementsAre("before", "at", "done", "after"));
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, CertificateError) {
  net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
  https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED);
  https_server.ServeFilesFromSourceDirectory(GetTestDataFilePath());
  ASSERT_TRUE(https_server.Start());
  GURL test_url = https_server.GetURL("/devtools/navigation.html");
  base::Value::Dict command_params;

  shell()->LoadURL(GURL("about:blank"));
  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));

  Attach();
  SendCommandSync("Network.enable");
  SendCommandAsync("Security.enable");
  command_params = base::Value::Dict();
  command_params.Set("override", true);
  SendCommandSync("Security.setOverrideCertificateErrors",
                  std::move(command_params));

  // Test cancel.
  SendCommandSync("Network.clearBrowserCache");
  SendCommandSync("Network.clearBrowserCookies");
  TestNavigationObserver cancel_observer(shell()->web_contents(), 1);
  shell()->LoadURL(test_url);
  base::Value::Dict params =
      WaitForNotification("Security.certificateError", false);
  EXPECT_TRUE(shell()->web_contents()->GetController().GetPendingEntry());
  EXPECT_EQ(
      test_url,
      shell()->web_contents()->GetController().GetPendingEntry()->GetURL());
  command_params = base::Value::Dict();
  command_params.Set("eventId", *params.FindInt("eventId"));
  command_params.Set("action", "cancel");
  SendCommandAsync("Security.handleCertificateError",
                   std::move(command_params));
  cancel_observer.Wait();
  EXPECT_FALSE(shell()->web_contents()->GetController().GetPendingEntry());
  EXPECT_EQ(GURL("about:blank"), shell()
                                     ->web_contents()
                                     ->GetController()
                                     .GetLastCommittedEntry()
                                     ->GetURL());

  // Test continue.
  SendCommandSync("Network.clearBrowserCache");
  SendCommandSync("Network.clearBrowserCookies");
  TestNavigationObserver continue_observer(shell()->web_contents(), 1);
  shell()->LoadURL(test_url);
  params = WaitForNotification("Security.certificateError", false);
  command_params = base::Value::Dict();
  command_params.Set("eventId", *params.FindInt("eventId"));
  command_params.Set("action", "continue");
  SendCommandAsync("Security.handleCertificateError",
                   std::move(command_params));
  WaitForNotification("Network.loadingFinished", true);
  continue_observer.Wait();
  EXPECT_EQ(test_url, shell()
                          ->web_contents()
                          ->GetController()
                          .GetLastCommittedEntry()
                          ->GetURL());

  // Reset override.
  SendCommandSync("Security.disable");

  // Test ignoring all certificate errors.
  command_params = base::Value::Dict();
  command_params.Set("ignore", true);
  SendCommandSync("Security.setIgnoreCertificateErrors",
                  std::move(command_params));

  SendCommandSync("Network.clearBrowserCache");
  SendCommandSync("Network.clearBrowserCookies");
  TestNavigationObserver continue_observer2(shell()->web_contents(), 1);
  shell()->LoadURL(test_url);
  WaitForNotification("Network.loadingFinished", true);
  continue_observer2.Wait();
  EXPECT_EQ(test_url, shell()
                          ->web_contents()
                          ->GetController()
                          .GetLastCommittedEntry()
                          ->GetURL());
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest,
                       CertificateErrorRequestInterception) {
  net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
  https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED);
  https_server.ServeFilesFromSourceDirectory(GetTestDataFilePath());
  ASSERT_TRUE(https_server.Start());
  GURL test_url = https_server.GetURL("/devtools/navigation.html");

  shell()->LoadURL(GURL("about:blank"));
  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));

  Attach();
  SendCommandSync("Network.enable");
  SendCommandAsync("Security.enable");
  SendCommandSync("Network.setRequestInterception",
                  std::move(base::JSONReader::Read(
                                "{\"patterns\": [{\"urlPattern\": \"*\"}]}")
                                ->GetDict()));

  SendCommandSync(
      "Security.setIgnoreCertificateErrors",
      std::move(base::JSONReader::Read("{\"ignore\": true}")->GetDict()));

  SendCommandSync("Network.clearBrowserCache");
  SendCommandSync("Network.clearBrowserCookies");
  TestNavigationObserver continue_observer(shell()->web_contents(), 1);
  shell()->LoadURL(test_url);
  base::Value::Dict params =
      WaitForNotification("Network.requestIntercepted", false);
  std::string interceptionId = *params.FindString("interceptionId");
  SendCommandAsync("Network.continueInterceptedRequest",
                   std::move(base::JSONReader::Read("{\"interceptionId\": \"" +
                                                    interceptionId + "\"}")
                                 ->GetDict()));
  continue_observer.Wait();
  EXPECT_EQ(test_url, shell()
                          ->web_contents()
                          ->GetController()
                          .GetLastCommittedEntry()
                          ->GetURL());
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, CertificateErrorBrowserTarget) {
  net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
  https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED);
  https_server.ServeFilesFromSourceDirectory(GetTestDataFilePath());
  ASSERT_TRUE(https_server.Start());
  GURL test_url = https_server.GetURL("/devtools/navigation.html");
  base::Value::Dict params;
  base::Value::Dict command_params;

  shell()->LoadURL(GURL("about:blank"));
  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));

  // Clear cookies and cache to avoid interference with cert error events.
  Attach();
  SendCommandSync("Network.enable");
  SendCommandSync("Network.clearBrowserCache");
  SendCommandSync("Network.clearBrowserCookies");
  Detach();

  // Test that browser target can ignore cert errors.
  AttachToBrowserTarget();
  command_params = base::Value::Dict();
  command_params.Set("ignore", true);
  SendCommandSync("Security.setIgnoreCertificateErrors",
                  std::move(command_params));

  TestNavigationObserver continue_observer(shell()->web_contents(), 1);
  shell()->LoadURL(test_url);
  continue_observer.Wait();
  EXPECT_EQ(test_url, shell()
                          ->web_contents()
                          ->GetController()
                          .GetLastCommittedEntry()
                          ->GetURL());
}

class CertificateErrorIgnoredBrowserTargetTest : public DevToolsProtocolTest {
 public:
  CertificateErrorIgnoredBrowserTargetTest()
      : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {}

  void SetUpOnMainThread() override {
    DevToolsProtocolTest::SetUpOnMainThread();
    net::SSLServerConfig ssl_config;
    // ssl_config.client_cert_type =
    //     net::SSLServerConfig::ClientCertType::REQUIRE_CLIENT_CERT;
    // https_server_.SetSSLConfig(net::EmbeddedTestServer::CERT_OK, ssl_config);

    https_server_.SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED);
    https_server_.ServeFilesFromSourceDirectory(GetTestDataFilePath());
    ASSERT_TRUE(https_server_.Start());
    GURL test_url = https_server_.GetURL("/devtools/navigation.html");

    shell()->LoadURL(GURL("about:blank"));
    EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));

    // Create a second client to concurrently connect to browser target,
    // as the DevToolsProtocolTest class only has one client available to
    // connect.
    browser_client.AttachToBrowserTarget();
    base::Value::Dict command_params;
    command_params = base::Value::Dict();
    command_params.Set("ignore", true);
    browser_client.SendCommandSync("Security.setIgnoreCertificateErrors",
                                   std::move(command_params));

    // Connect the default client to the page.
    Attach();
    SendCommandSync("Debugger.enable");
    // Clear cookies and cache to avoid interference with cert error events.
    SendCommandSync("Network.enable");
    SendCommandSync("Network.clearBrowserCache");
    SendCommandSync("Network.clearBrowserCookies");

    TestNavigationObserver continue_observer(shell()->web_contents(), 1);
    shell()->LoadURL(test_url);
    continue_observer.Wait();

    EXPECT_EQ(test_url, shell()
                            ->web_contents()
                            ->GetController()
                            .GetLastCommittedEntry()
                            ->GetURL());
  }

  void TearDownOnMainThread() override {
    // Detach the additional client
    browser_client.DetachProtocolClient();
    DevToolsProtocolTest::TearDownOnMainThread();
  }

  ~CertificateErrorIgnoredBrowserTargetTest() override = default;

 protected:
  TestDevToolsProtocolClient browser_client;
  net::EmbeddedTestServer https_server_;
};

IN_PROC_BROWSER_TEST_F(CertificateErrorIgnoredBrowserTargetTest,
                       CertificateErrorBrowserTargetServiceWorkerFetch) {
  // Install a service worker over bad HTTPS cert and wait for the controller to
  // change.
  base::Value::Dict params;
  ASSERT_TRUE(content::ExecJs(
      shell()->web_contents(),
      "navigator.serviceWorker.register('/devtools/service_worker.js');"
      "navigator.serviceWorker.oncontrollerchange = () => {debugger;};"));
  WaitForNotification("Debugger.paused");
  SendCommandSync("Debugger.resume");
  // Reload the page so that request is intercepted by SW.
  SendCommandSync("Page.reload");
  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
  EXPECT_EQ("intercepted",
            EvalJs(shell()->web_contents(), "document.body.textContent"));
}

IN_PROC_BROWSER_TEST_F(
    CertificateErrorIgnoredBrowserTargetTest,
    CertificateErrorBrowserTargetServiceWorkerImportScripts) {
  // Install a service worker over bad HTTPS cert and wait for the controller to
  // change.
  base::Value::Dict params;
  ASSERT_TRUE(content::ExecJs(
      shell()->web_contents(),
      "navigator.serviceWorker.register('/devtools/"
      "service_worker_import_classic.js');"
      "navigator.serviceWorker.oncontrollerchange = () => {debugger;};"));
  WaitForNotification("Debugger.paused");

  SendCommandSync("Debugger.resume");

  // Reload the page so that request is intercepted by SW.
  SendCommandSync("Page.reload");
  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));

  EXPECT_EQ("imported",
            EvalJs(shell()->web_contents(), "document.body.textContent"));
}

IN_PROC_BROWSER_TEST_F(CertificateErrorIgnoredBrowserTargetTest,
                       CertificateErrorBrowserTargetServiceWorkerModuleImport) {
  // Install a service worker over bad HTTPS cert and wait for the controller to
  // change.
  base::Value::Dict params;
  ASSERT_TRUE(content::ExecJs(
      shell()->web_contents(),
      "navigator.serviceWorker.register('/devtools/"
      "service_worker_import_module.js', {type: 'module'});"
      "navigator.serviceWorker.oncontrollerchange = () => {debugger;};"));
  WaitForNotification("Debugger.paused");

  SendCommandSync("Debugger.resume");

  // Reload the page so that request is intercepted by SW.
  SendCommandSync("Page.reload");
  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));

  EXPECT_EQ("imported",
            EvalJs(shell()->web_contents(), "document.body.textContent"));
}

IN_PROC_BROWSER_TEST_F(CertificateErrorIgnoredBrowserTargetTest,
                       CertificateErrorBrowserTargetDedicatedWorker) {
  // Install a dedicated worker over bad HTTPS cert.
  base::Value::Dict params;
  ASSERT_TRUE(content::ExecJs(
      shell()->web_contents(),
      "const myWorker = new Worker('/devtools/dedicated_worker.js');"
      "myWorker.onmessage = (msg) => {document.body.textContent = msg.data; "
      "debugger;};"
      "myWorker.postMessage('test');"));

  WaitForNotification("Debugger.paused");
  SendCommandSync("Debugger.resume");

  EXPECT_EQ("reply test",
            EvalJs(shell()->web_contents(), "document.body.textContent"));
}

IN_PROC_BROWSER_TEST_F(
    CertificateErrorIgnoredBrowserTargetTest,
    CertificateErrorBrowserTargetDedicatedWorkerImportClassic) {
  // Install a dedicated worker over bad HTTPS cert.
  base::Value::Dict params;
  ASSERT_TRUE(content::ExecJs(
      shell()->web_contents(),
      "const myWorker = new "
      "Worker('/devtools/dedicated_worker_import_classic.js');"
      "myWorker.onmessage = (msg) => {document.body.textContent = msg.data; "
      "debugger;};"
      "myWorker.postMessage('test');"));

  WaitForNotification("Debugger.paused");
  SendCommandSync("Debugger.resume");

  EXPECT_EQ("reply imported test",
            EvalJs(shell()->web_contents(), "document.body.textContent"));
}

IN_PROC_BROWSER_TEST_F(
    CertificateErrorIgnoredBrowserTargetTest,
    CertificateErrorBrowserTargetDedicatedWorkerImportModule) {
  // Install a dedicated worker over bad HTTPS cert.
  base::Value::Dict params;
  ASSERT_TRUE(content::ExecJs(
      shell()->web_contents(),
      "const myWorker = new "
      "Worker('/devtools/dedicated_worker_import_module.js', {type: 'module'});"
      "myWorker.onmessage = (msg) => {document.body.textContent = msg.data; "
      "debugger;};"
      "myWorker.postMessage('test');"));

  WaitForNotification("Debugger.paused");
  SendCommandSync("Debugger.resume");

  EXPECT_EQ("reply imported test",
            EvalJs(shell()->web_contents(), "document.body.textContent"));
}

// SharedWorkers are not enabled on Android. https://crbug.com/154571
#if BUILDFLAG(IS_ANDROID)
constexpr bool kIsSharedWorkerEnabled = false;
#else
constexpr bool kIsSharedWorkerEnabled = true;
#endif

IN_PROC_BROWSER_TEST_F(CertificateErrorIgnoredBrowserTargetTest,
                       CertificateErrorBrowserTargetSharedWorker) {
  if (!kIsSharedWorkerEnabled) {
    return;
  }
  // Install a shared worker over bad HTTPS cert.
  base::Value::Dict params;
  ASSERT_TRUE(content::ExecJs(
      shell()->web_contents(),
      "const myWorker = new SharedWorker('/devtools/shared_worker.js');"
      "myWorker.port.start();"
      "myWorker.port.onmessage = (msg) => {document.body.textContent = "
      "msg.data; debugger;};"
      "myWorker.port.postMessage('test');"));
  WaitForNotification("Debugger.paused");
  SendCommandSync("Debugger.resume");

  EXPECT_EQ("reply test",
            EvalJs(shell()->web_contents(), "document.body.textContent"));
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, SubresourceWithCertificateError) {
  net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
  https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED);
  https_server.ServeFilesFromSourceDirectory("content/test/data/devtools");
  ASSERT_TRUE(https_server.Start());
  GURL test_url = https_server.GetURL("/image.html");
  base::Value::Dict command_params;

  shell()->LoadURL(GURL("about:blank"));
  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));

  Attach();
  SendCommandAsync("Security.enable");
  command_params = base::Value::Dict();
  command_params.Set("override", true);
  SendCommandSync("Security.setOverrideCertificateErrors",
                  std::move(command_params));

  TestNavigationObserver observer(shell()->web_contents(), 1);
  shell()->LoadURL(test_url);

  // Expect certificateError event for main frame.
  base::Value::Dict params =
      WaitForNotification("Security.certificateError", false);
  command_params = base::Value::Dict();
  command_params.Set("eventId", *params.FindInt("eventId"));
  command_params.Set("action", "continue");
  SendCommandAsync("Security.handleCertificateError",
                   std::move(command_params));

  // Expect certificateError event for image.
  params = WaitForNotification("Security.certificateError", false);
  command_params = base::Value::Dict();
  command_params.Set("eventId", *params.FindInt("eventId"));
  command_params.Set("action", "continue");
  SendCommandAsync("Security.handleCertificateError",
                   std::move(command_params));

  observer.Wait();
  EXPECT_EQ(test_url, shell()
                          ->web_contents()
                          ->GetController()
                          .GetLastCommittedEntry()
                          ->GetURL());
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, TargetDiscovery) {
  std::set<std::string> ids;
  base::Value::Dict command_params;

  ASSERT_TRUE(embedded_test_server()->Start());
  GURL first_url = embedded_test_server()->GetURL("/devtools/navigation.html");
  NavigateToURLBlockUntilNavigationsComplete(shell(), first_url, 1);

  GURL second_url = embedded_test_server()->GetURL("/devtools/navigation.html");
  Shell* second = CreateBrowser();
  NavigateToURLBlockUntilNavigationsComplete(second, second_url, 1);

  Attach();
  int attached_count = 0;
  command_params = base::Value::Dict();
  command_params.Set("discover", true);
  SendCommandSync("Target.setDiscoverTargets", std::move(command_params));
  base::Value::Dict params = WaitForNotification("Target.targetCreated", true);
  EXPECT_THAT(*params.FindStringByDottedPath("targetInfo.type"), Eq("page"));
  attached_count += *params.FindBoolByDottedPath("targetInfo.attached") ? 1 : 0;
  std::string target_id = *params.FindStringByDottedPath("targetInfo.targetId");
  EXPECT_THAT(ids.count(target_id), Eq(0u));
  ids.insert(target_id);
  params = WaitForNotification("Target.targetCreated", true);
  EXPECT_THAT(*params.FindStringByDottedPath("targetInfo.type"), Eq("page"));
  attached_count += *params.FindBoolByDottedPath("targetInfo.attached") ? 1 : 0;
  target_id = *params.FindStringByDottedPath("targetInfo.targetId");
  EXPECT_THAT(ids.count(target_id), Eq(0u));
  ids.insert(target_id);
  EXPECT_FALSE(HasExistingNotification());
  EXPECT_EQ(1, attached_count);

  GURL third_url = embedded_test_server()->GetURL("/devtools/navigation.html");
  Shell* third = CreateBrowser();
  NavigateToURLBlockUntilNavigationsComplete(third, third_url, 1);

  params = WaitForNotification("Target.targetCreated", true);
  EXPECT_THAT(*params.FindStringByDottedPath("targetInfo.type"), Eq("page"));
  std::string attached_id =
      *params.FindStringByDottedPath("targetInfo.targetId");
  EXPECT_THAT(ids.count(attached_id), Eq(0u));
  ids.insert(attached_id);
  EXPECT_THAT(params.FindBoolByDottedPath("targetInfo.attached"),
              testing::Optional(false));

  params = WaitForNotification("Target.targetInfoChanged", true);
  EXPECT_THAT(*params.FindStringByDottedPath("targetInfo.url"),
              Eq("about:blank"));

  params = WaitForNotification("Target.targetInfoChanged", true);
  EXPECT_THAT(*params.FindStringByDottedPath("targetInfo.url"),
              Eq(third_url.spec()));
  EXPECT_FALSE(HasExistingNotification());

  second->Close();
  second = nullptr;
  params = WaitForNotification("Target.targetDestroyed", true);
  target_id = *params.FindString("targetId");
  EXPECT_THAT(ids.erase(target_id), Eq(1u));
  EXPECT_FALSE(HasExistingNotification());

  command_params = base::Value::Dict();
  command_params.Set("targetId", attached_id);
  SendCommandSync("Target.attachToTarget", std::move(command_params));
  params = WaitForNotification("Target.targetInfoChanged", true);
  EXPECT_THAT(*params.FindStringByDottedPath("targetInfo.targetId"),
              Eq(attached_id));
  EXPECT_THAT(params.FindBoolByDottedPath("targetInfo.attached"),
              testing::Optional(true));
  params = WaitForNotification("Target.attachedToTarget", true);
  std::string session_id = *params.FindString("sessionId");
  EXPECT_THAT(*params.FindStringByDottedPath("targetInfo.targetId"),
              Eq(attached_id));
  EXPECT_FALSE(HasExistingNotification());

  WebContents::CreateParams create_params(
      ShellContentBrowserClient::Get()->browser_context());
  std::unique_ptr<content::WebContents> web_contents(
      content::WebContents::Create(create_params));
  EXPECT_FALSE(HasExistingNotification());

  NavigateToURLBlockUntilNavigationsComplete(web_contents.get(), first_url, 1);
  // The notification does not come when there's no delegate.
  EXPECT_FALSE(HasExistingNotification("Target.targetCreated"));

  web_contents->SetDelegate(this);
  // Attaching a delegate causes the notification to be sent.
  params = WaitForNotification("Target.targetCreated", true);
  EXPECT_THAT(*params.FindStringByDottedPath("targetInfo.type"), Eq("page"));
  EXPECT_FALSE(HasExistingNotification());

  command_params = base::Value::Dict();
  command_params.Set("discover", false);
  SendCommandSync("Target.setDiscoverTargets", std::move(command_params));
  EXPECT_FALSE(HasExistingNotification());

  command_params = base::Value::Dict();
  command_params.Set("sessionId", session_id);
  SendCommandSync("Target.detachFromTarget", std::move(command_params));
  params = WaitForNotification("Target.detachedFromTarget", true);
  EXPECT_THAT(*params.FindString("sessionId"), Eq(session_id));
  EXPECT_THAT(*params.FindString("targetId"), Eq(attached_id));
  EXPECT_FALSE(HasExistingNotification());
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, SetAndGetCookies) {
  ASSERT_TRUE(embedded_test_server()->Start());
  GURL test_url = embedded_test_server()->GetURL("/title1.html");
  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1);
  Attach();

  // Set two cookies, one of which matches the loaded URL and another that
  // doesn't.
  base::Value::Dict command_params;
  command_params = base::Value::Dict();
  command_params.Set("url", test_url.spec());
  command_params.Set("name", "cookie_for_this_url");
  command_params.Set("value", "mendacious");
  SendCommandAsync("Network.setCookie", std::move(command_params));

  command_params = base::Value::Dict();
  command_params.Set("url", "https://www.chromium.org");
  command_params.Set("name", "cookie_for_another_url");
  command_params.Set("value", "polyglottal");
  SendCommandAsync("Network.setCookie", std::move(command_params));

  // First get the cookies for just the loaded URL.
  SendCommandSync("Network.getCookies");

  const base::Value::List* cookies = result()->FindList("cookies");
  ASSERT_TRUE(cookies);
  EXPECT_EQ(1u, cookies->size());

  const std::string* name = nullptr;
  const std::string* value = nullptr;
  {
    ASSERT_TRUE(cookies->front().is_dict());
    const base::Value::Dict& cookie = cookies->front().GetDict();
    name = cookie.FindString("name");
    value = cookie.FindString("value");
    ASSERT_TRUE(name);
    ASSERT_TRUE(value);
    EXPECT_EQ("cookie_for_this_url", *name);
    EXPECT_EQ("mendacious", *value);

    // Then get all the cookies in the cookie jar.
    SendCommandSync("Network.getAllCookies");

    cookies = result()->FindList("cookies");
    ASSERT_TRUE(cookies);
    EXPECT_EQ(2u, cookies->size());
  }

  // Note: the cookies will be returned in unspecified order.
  size_t found = 0;
  for (const base::Value& cookie_value : *cookies) {
    ASSERT_TRUE(cookie_value.is_dict());
    const base::Value::Dict& cookie = cookie_value.GetDict();
    name = cookie.FindString("name");
    value = cookie.FindString("value");
    ASSERT_TRUE(name);
    ASSERT_TRUE(value);
    if (*name == "cookie_for_this_url") {
      EXPECT_EQ("mendacious", *value);
      found++;
    } else if (*name == "cookie_for_another_url") {
      EXPECT_EQ("polyglottal", *value);
      found++;
    } else {
      FAIL();
    }
  }
  EXPECT_EQ(2u, found);
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest,
                       ReturnsCookiesOnlyForAttachableUrls) {
  SetNotAttachableHosts({"b.test"});
  content::SetupCrossSiteRedirector(embedded_test_server());
  ASSERT_TRUE(embedded_test_server()->Start());
  std::string cookies_to_set = "/set-cookie?foo=bar";

  GURL url = embedded_test_server()->GetURL("b.test", cookies_to_set);
  EXPECT_TRUE(NavigateToURL(shell(), url));
  url = embedded_test_server()->GetURL("c.test", cookies_to_set);
  EXPECT_TRUE(NavigateToURL(shell(), url));
  url = embedded_test_server()->GetURL(
      "a.test", "/cross_site_iframe_factory.html?a.test(b.test(),c.test())");
  EXPECT_TRUE(NavigateToURL(shell(), url));

  Attach();
  const base::Value::List* storage_cookies =
      SendCommandSync("Storage.getCookies")->FindList("cookies");
  ASSERT_EQ(1ul, storage_cookies->size());
  EXPECT_EQ("foo", *storage_cookies->front().GetDict().FindString("name"));
  EXPECT_EQ("c.test", *storage_cookies->front().GetDict().FindString("domain"));

  const base::Value::List* network_all_cookies =
      SendCommandSync("Network.getAllCookies")->FindList("cookies");
  ASSERT_EQ(1ul, network_all_cookies->size());
  EXPECT_EQ("foo", *network_all_cookies->front().GetDict().FindString("name"));
  EXPECT_EQ("c.test",
            *network_all_cookies->front().GetDict().FindString("domain"));

  const base::Value::List* network_cookies_no_param =
      SendCommandSync("Network.getCookies")->FindList("cookies");
  ASSERT_EQ(1ul, network_cookies_no_param->size());
  EXPECT_EQ("foo",
            *network_cookies_no_param->front().GetDict().FindString("name"));
  EXPECT_EQ("c.test",
            *network_cookies_no_param->front().GetDict().FindString("domain"));

  base::Value::List urls;
  urls.Append(embedded_test_server()
                  ->GetURL("b.com", "/cross_site_iframe_factory.html?b.test()")
                  .spec());
  urls.Append(embedded_test_server()
                  ->GetURL("c.com", "/cross_site_iframe_factory.html?c.test()")
                  .spec());
  base::Value::Dict params;
  params.Set("urls", std::move(urls));
  const base::Value::List* network_cookies_with_param =
      SendCommandSync("Network.getAllCookies", std::move(params))
          ->FindList("cookies");
  ASSERT_EQ(1ul, network_cookies_with_param->size());
  EXPECT_EQ("foo",
            *network_cookies_with_param->front().GetDict().FindString("name"));
  EXPECT_EQ("c.test", *network_cookies_with_param->front().GetDict().FindString(
                          "domain"));
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest,
                       AutoAttachToOOPIFAfterNavigationStarted) {
  ASSERT_TRUE(embedded_test_server()->Start());
  IsolateOriginsForTesting(embedded_test_server(), shell()->web_contents(),
                           {"b.com"});
  GURL a_url = embedded_test_server()->GetURL("a.com", "/title1.html");
  EXPECT_TRUE(NavigateToURL(shell(), a_url));
  RenderFrameHostImpl* main_frame = static_cast<RenderFrameHostImpl*>(
      shell()->web_contents()->GetPrimaryMainFrame());

  // Create iframe and start navigation.
  GURL b_url(embedded_test_server()->GetURL("b.com", "/title1.html"));
  TestNavigationManager navigation_manager(shell()->web_contents(), b_url);
  EXPECT_TRUE(ExecJs(
      main_frame, JsReplace("const iframe = document.createElement('iframe');\n"
                            "iframe.src = $1;\n"
                            "document.body.appendChild(iframe);\n",
                            b_url)));
  // Pause subframe navigation.
  EXPECT_TRUE(navigation_manager.WaitForRequestStart());

  // Attach to DevTools after subframe starts navigating (but before it
  // finishes).
  Attach();

  DevToolsAgentHostImpl* main_frame_agent =
      RenderFrameDevToolsAgentHost::GetFor(main_frame);
  EXPECT_NE(main_frame_agent, nullptr);

  // Start auto-attach.
  base::Value::Dict command_params;
  command_params = base::Value::Dict();
  command_params.Set("autoAttach", true);
  command_params.Set("waitForDebuggerOnStart", false);
  command_params.Set("flatten", true);
  SendCommandSync("Target.setAutoAttach", std::move(command_params));

  // Child frame should be created at this point, but isn't an OOPIF yet, so
  // shouldn't have its own DevToolsAgentHost yet.
  FrameTreeNode* child = main_frame->child_at(0);
  EXPECT_NE(child, nullptr);
  EXPECT_EQ(RenderFrameDevToolsAgentHost::GetFor(child), main_frame_agent);

  // Resume navigation.
  ASSERT_TRUE(navigation_manager.WaitForNavigationFinished());

  // Target for OOPIF should get attached.
  auto notification = WaitForNotification("Target.attachedToTarget", true);
  EXPECT_NE(RenderFrameDevToolsAgentHost::GetFor(child), main_frame_agent);
  EXPECT_THAT(notification.FindBool("waitingForDebugger"),
              testing::Optional(false));
}

class DevToolsProtocolDeviceEmulationTest : public DevToolsProtocolTest {
 public:
  ~DevToolsProtocolDeviceEmulationTest() override {}

  void EmulateDeviceSize(gfx::Size size) {
    base::Value::Dict params;
    params.Set("width", size.width());
    params.Set("height", size.height());
    params.Set("deviceScaleFactor", 0);
    params.Set("mobile", false);
    SendCommandSync("Emulation.setDeviceMetricsOverride", std::move(params));
  }

  gfx::Size GetViewSize() {
    return shell()
        ->web_contents()
        ->GetPrimaryMainFrame()
        ->GetView()
        ->GetViewBounds()
        .size();
  }
};

// Setting frame size (through RWHV) is not supported on Android.
#if BUILDFLAG(IS_ANDROID)
#define MAYBE_DeviceSize DISABLED_DeviceSize
#else
#define MAYBE_DeviceSize DeviceSize
#endif
IN_PROC_BROWSER_TEST_F(DevToolsProtocolDeviceEmulationTest, MAYBE_DeviceSize) {
  content::SetupCrossSiteRedirector(embedded_test_server());
  ASSERT_TRUE(embedded_test_server()->Start());

  GURL test_url1 =
      embedded_test_server()->GetURL("A.com", "/devtools/navigation.html");
  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url1, 1);
  Attach();

  const gfx::Size original_size = GetViewSize();
  const gfx::Size emulated_size_1 =
      gfx::Size(original_size.width() - 50, original_size.height() - 50);
  const gfx::Size emulated_size_2 =
      gfx::Size(original_size.width() - 100, original_size.height() - 100);

  EmulateDeviceSize(emulated_size_1);
  EXPECT_EQ(emulated_size_1, GetViewSize());

  EmulateDeviceSize(emulated_size_2);
  EXPECT_EQ(emulated_size_2, GetViewSize());

  GURL test_url2 =
      embedded_test_server()->GetURL("B.com", "/devtools/navigation.html");
  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url2, 1);
  EXPECT_EQ(emulated_size_2, GetViewSize());

  SendCommandSync("Emulation.clearDeviceMetricsOverride");
  EXPECT_EQ(original_size, GetViewSize());
}

// Setting frame size (through RWHV) is not supported on Android.
#if BUILDFLAG(IS_ANDROID)
#define MAYBE_RenderKillDoesNotCrashBrowser \
  DISABLED_RenderKillDoesNotCrashBrowser
#else
#define MAYBE_RenderKillDoesNotCrashBrowser RenderKillDoesNotCrashBrowser
#endif
IN_PROC_BROWSER_TEST_F(DevToolsProtocolDeviceEmulationTest,
                       MAYBE_RenderKillDoesNotCrashBrowser) {
  NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
  Attach();
  EmulateDeviceSize(gfx::Size(200, 200));

  {
    ScopedAllowRendererCrashes scoped_allow_renderer_crashes(shell());
    NavigateToURLBlockUntilNavigationsComplete(
        shell(), GURL(blink::kChromeUICrashURL), 1);
  }

  SendCommandSync("Emulation.clearDeviceMetricsOverride");
  // Should not crash at this point.
}

class DevToolsProtocolDeviceEmulationPrerenderTest
    : public DevToolsProtocolDeviceEmulationTest {
 public:
  DevToolsProtocolDeviceEmulationPrerenderTest()
      : prerender_helper_(base::BindRepeating(
            &DevToolsProtocolDeviceEmulationPrerenderTest::GetWebContents,
            base::Unretained(this))) {}
  ~DevToolsProtocolDeviceEmulationPrerenderTest() override = default;

  void SetUpOnMainThread() override {
    DevToolsProtocolDeviceEmulationTest::SetUpOnMainThread();
    prerender_helper_.RegisterServerRequestMonitor(embedded_test_server());
  }

  // WebContentsDelegate overrides.
  PreloadingEligibility IsPrerender2Supported(
      WebContents& web_contents,
      PreloadingTriggerType trigger_type) override {
    return PreloadingEligibility::kEligible;
  }

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

  std::string AttachToTabTargetAndGetSessionId() {
    AttachToTabTarget(shell()->web_contents());
    shell()->web_contents()->SetDelegate(this);

    {
      base::Value::Dict params;
      params.Set("discover", true);
      SendCommandSync("Target.setDiscoverTargets", std::move(params));
    }

    std::string frame_target_id;
    for (int targetCount = 1; true; targetCount++) {
      base::Value::Dict result;
      result = WaitForNotification("Target.targetCreated", true);
      if (*result.FindStringByDottedPath("targetInfo.type") == "page") {
        frame_target_id =
            std::string(*result.FindStringByDottedPath("targetInfo.targetId"));
        break;
      }
      CHECK_LT(targetCount, 2);
    }

    {
      base::Value::Dict params;
      params.Set("targetId", frame_target_id);
      params.Set("flatten", true);
      const base::Value::Dict* result =
          SendCommandSync("Target.attachToTarget", std::move(params));
      CHECK(result);
      std::string session_id(*result->FindString("sessionId"));
      CHECK(session_id != "");
      return session_id;
    }
  }

 protected:
  test::PrerenderTestHelper prerender_helper_;
};

// Setting frame size (through RWHV) is not supported on Android.
#if BUILDFLAG(IS_ANDROID)
#define MAYBE_DeviceSize DISABLED_DeviceSize
#else
#define MAYBE_DeviceSize DeviceSize
#endif
IN_PROC_BROWSER_TEST_F(DevToolsProtocolDeviceEmulationPrerenderTest,
                       MAYBE_DeviceSize) {
  SetupCrossSiteRedirector(embedded_test_server());
  ASSERT_TRUE(embedded_test_server()->Start());

  GURL test_url = embedded_test_server()->GetURL("/devtools/navigation.html");
  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1);
  std::string session_id = AttachToTabTargetAndGetSessionId();

  const gfx::Size original_size = GetViewSize();
  const gfx::Size emulated_size =
      gfx::Size(original_size.width() - 50, original_size.height() - 50);

  {
    const gfx::Size size = emulated_size;
    base::Value::Dict params;
    params.Set("width", size.width());
    params.Set("height", size.height());
    params.Set("deviceScaleFactor", 0);
    params.Set("mobile", false);
    SendSessionCommand("Emulation.setDeviceMetricsOverride", std::move(params),
                       session_id, true);
  }
  EXPECT_EQ(emulated_size, GetViewSize());

  // Start a prerender and ensure frame size isn't changed.
  GURL prerender_url =
      embedded_test_server()->GetURL("/devtools/navigation.html?prerender");
  prerender_helper_.AddPrerender(prerender_url);
  EXPECT_EQ(emulated_size, GetViewSize());

  // Activate the prerendered page and ensure frame size isn't changed.
  prerender_helper_.NavigatePrimaryPage(prerender_url);
  EXPECT_EQ(emulated_size, GetViewSize());

  SendSessionCommand("Emulation.clearDeviceMetricsOverride",
                     base::Value::Dict(), session_id, true);
  EXPECT_EQ(original_size, GetViewSize());
}

class DevToolsProtocolTouchTest : public DevToolsProtocolTest {
 public:
  ~DevToolsProtocolTouchTest() override {}

  void SetUpCommandLine(base::CommandLine* command_line) override {
    command_line->AppendSwitchASCII(
        switches::kTouchEventFeatureDetection,
        switches::kTouchEventFeatureDetectionDisabled);
  }
};

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTouchTest, EnableTouch) {
  base::Value::Dict params;

  content::SetupCrossSiteRedirector(embedded_test_server());
  ASSERT_TRUE(embedded_test_server()->Start());
  GURL test_url1 =
      embedded_test_server()->GetURL("A.com", "/devtools/enable_touch.html");
  GURL test_url2 =
      embedded_test_server()->GetURL("B.com", "/devtools/enable_touch.html");
  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url1, 1);
  Attach();

  params = base::Value::Dict();
  SendCommandSync("Page.enable", std::move(params));

  EXPECT_EQ(true, EvalJs(shell()->web_contents(), "checkProtos(false)"));

  params = base::Value::Dict();
  params.Set("enabled", true);
  SendCommandSync("Emulation.setTouchEmulationEnabled", std::move(params));
  EXPECT_EQ(true, EvalJs(shell()->web_contents(), "checkProtos(false)"));

  params = base::Value::Dict();
  params.Set("url", test_url2.spec());
  SendCommandAsync("Page.navigate", std::move(params));
  WaitForNotification("Page.frameStoppedLoading");
  EXPECT_EQ(true, EvalJs(shell()->web_contents(), "checkProtos(true)"));

  params = base::Value::Dict();
  params.Set("enabled", false);
  SendCommandSync("Emulation.setTouchEmulationEnabled", std::move(params));
  EXPECT_EQ(true, EvalJs(shell()->web_contents(), "checkProtos(true)"));

  params = base::Value::Dict();
  SendCommandAsync("Page.reload", std::move(params));
  WaitForNotification("Page.frameStoppedLoading");
  EXPECT_EQ(true, EvalJs(shell()->web_contents(), "checkProtos(false)"));
}

class DevToolsProtocolBackForwardCacheTest : public DevToolsProtocolTest {
 public:
  DevToolsProtocolBackForwardCacheTest() {
    feature_list_.InitWithFeaturesAndParameters(
        GetDefaultEnabledBackForwardCacheFeaturesForTesting(
            /*ignore_outstanding_network_request=*/false),
        GetDefaultDisabledBackForwardCacheFeaturesForTesting());
  }
  ~DevToolsProtocolBackForwardCacheTest() override = default;

  // content::WebContentsDelegate:
  bool IsBackForwardCacheSupported(
      content::WebContents& web_contents) override {
    return true;
  }

  std::string Evaluate(const std::string& script,
                       const base::Location& location) {
    base::Value::Dict params;
    params.Set("expression", script);
    SendCommandSync("Runtime.evaluate", std::move(params));
    const std::string* result_value =
        result()->FindStringByDottedPath("result.value");
    DCHECK(result_value) << "Valued to evaluate " << script << " from "
                         << location.ToString();
    return *result_value;
  }

 private:
  base::test::ScopedFeatureList feature_list_;
};

// This test checks that the DevTools continue to work when the page is stored
// in and restored from back-forward cache. In particular:
// - that the session continues to be attached and the navigations are handled
// correctly.
// - when the old page is stored in the cache, the messages are still handled by
// the new page.
// - when the page is restored from the cache, it continues to handle protocol
// messages.
IN_PROC_BROWSER_TEST_F(DevToolsProtocolBackForwardCacheTest, Basic) {
  ASSERT_TRUE(embedded_test_server()->Start());
  GURL url_a(embedded_test_server()->GetURL("a.com", "/title1.html"));
  GURL url_b(embedded_test_server()->GetURL("b.com", "/title1.html"));

  // 1) Navigate to A and inject some state.
  EXPECT_TRUE(NavigateToURL(shell(), url_a));
  EXPECT_TRUE(ExecJs(shell(), "var state = 'page1'"));

  // 2) Attach DevTools session.
  Attach();

  // 3) Extract the state via the DevTools protocol.
  EXPECT_EQ("page1", Evaluate("state", FROM_HERE));

  // 3) Navigate to B and inject some different state.
  EXPECT_TRUE(NavigateToURL(shell(), url_b));
  EXPECT_TRUE(ExecJs(shell(), "var state = 'page2'"));

  // 4) Ensure that the DevTools protocol commands are handled by the new page
  // (even though the old page is alive and is stored in the back-forward
  // cache).
  EXPECT_EQ("page2", Evaluate("state", FROM_HERE));

  // 5) Go back.
  shell()->web_contents()->GetController().GoBack();
  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));

  // 6) Ensure that the page has been restored from the cache and responds to
  // the DevTools commands.
  EXPECT_EQ("page1", Evaluate("state", FROM_HERE));
}

// Download tests are flaky on Android: https://crbug.com/7546
#if !BUILDFLAG(IS_ANDROID)
namespace {

static DownloadManagerImpl* DownloadManagerForShell(Shell* shell) {
  // We're in a content_browsertest; we know that the DownloadManager
  // is a DownloadManagerImpl.
  return static_cast<DownloadManagerImpl*>(
      shell->web_contents()->GetBrowserContext()->GetDownloadManager());
}

static void RemoveShellDelegate(Shell* shell) {
  content::ShellDownloadManagerDelegate* shell_delegate =
      static_cast<content::ShellDownloadManagerDelegate*>(
          DownloadManagerForShell(shell)->GetDelegate());
  shell_delegate->SetDownloadManager(nullptr);
  DownloadManagerForShell(shell)->SetDelegate(nullptr);
}

class CountingDownloadFile : public download::DownloadFileImpl {
 public:
  CountingDownloadFile(
      std::unique_ptr<download::DownloadSaveInfo> save_info,
      const base::FilePath& default_downloads_directory,
      std::unique_ptr<download::InputStream> stream,
      uint32_t download_id,
      base::WeakPtr<download::DownloadDestinationObserver> observer)
      : download::DownloadFileImpl(std::move(save_info),
                                   default_downloads_directory,
                                   std::move(stream),
                                   download_id,
                                   observer) {}

  ~CountingDownloadFile() override {
    DCHECK(download::GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
    active_files_--;
  }

  void Initialize(
      InitializeCallback callback,
      CancelRequestCallback cancel_request_callback,
      const download::DownloadItem::ReceivedSlices& received_slices) override {
    DCHECK(download::GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
    active_files_++;
    download::DownloadFileImpl::Initialize(std::move(callback),
                                           std::move(cancel_request_callback),
                                           received_slices);
  }

  static void GetNumberActiveFiles(int* result) {
    DCHECK(download::GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
    *result = active_files_;
  }

  // Can be called on any thread, and will block (running message loop)
  // until data is returned.
  static int GetNumberActiveFilesFromFileThread() {
    int result = -1;
    base::RunLoop run_loop;
    download::GetDownloadTaskRunner()->PostTaskAndReply(
        FROM_HERE,
        base::BindOnce(&CountingDownloadFile::GetNumberActiveFiles, &result),
        run_loop.QuitWhenIdleClosure());
    run_loop.Run();
    DCHECK_NE(-1, result);
    return result;
  }

 private:
  static int active_files_;
};

int CountingDownloadFile::active_files_ = 0;

class CountingDownloadFileFactory : public download::DownloadFileFactory {
 public:
  CountingDownloadFileFactory() {}
  ~CountingDownloadFileFactory() override {}

  // DownloadFileFactory interface.
  download::DownloadFile* CreateFile(
      std::unique_ptr<download::DownloadSaveInfo> save_info,
      const base::FilePath& default_downloads_directory,
      std::unique_ptr<download::InputStream> stream,
      uint32_t download_id,
      const base::FilePath& duplicate_download_file_path,
      base::WeakPtr<download::DownloadDestinationObserver> observer) override {
    return new CountingDownloadFile(std::move(save_info),
                                    default_downloads_directory,
                                    std::move(stream), download_id, observer);
  }
};

// Get the next created download.
class DownloadCreateObserver : DownloadManager::Observer {
 public:
  explicit DownloadCreateObserver(DownloadManager* manager)
      : manager_(manager), item_(nullptr), received_item_response_(false) {
    manager_->AddObserver(this);
  }

  ~DownloadCreateObserver() override {
    if (manager_)
      manager_->RemoveObserver(this);
    manager_ = nullptr;
  }

  void ManagerGoingDown(DownloadManager* manager) override {
    DCHECK_EQ(manager_, manager);
    manager_->RemoveObserver(this);
    manager_ = nullptr;
  }

  void OnDownloadCreated(DownloadManager* manager,
                         download::DownloadItem* download) override {
    received_item_response_ = true;

    if (!item_)
      item_ = download;

    if (completion_closure_)
      std::move(completion_closure_).Run();
  }

  void OnDownloadDropped(DownloadManager* manager) override {
    received_item_response_ = true;

    item_ = nullptr;
    if (completion_closure_)
      std::move(completion_closure_).Run();
  }

  download::DownloadItem* WaitForFinished() {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    if (!received_item_response_) {
      base::RunLoop run_loop;
      completion_closure_ = run_loop.QuitClosure();
      run_loop.Run();
    }
    return item_;
  }

 private:
  raw_ptr<DownloadManager> manager_;
  raw_ptr<download::DownloadItem> item_;
  bool received_item_response_;
  base::OnceClosure completion_closure_;
};

bool IsDownloadInState(download::DownloadItem::DownloadState state,
                       download::DownloadItem* item) {
  return item->GetState() == state;
}

class DevToolsDownloadContentTest : public DevToolsProtocolTest {
 protected:
  void SetUpOnMainThread() override {
    base::ScopedAllowBlockingForTesting allow_blocking;
    ASSERT_TRUE(downloads_directory_.CreateUniqueTempDir());

    // Set shell default download manager to test proxy reset behavior.
    test_delegate_ = std::make_unique<ShellDownloadManagerDelegate>();
    test_delegate_->SetDownloadBehaviorForTesting(
        downloads_directory_.GetPath());
    DownloadManager* manager = DownloadManagerForShell(shell());
    manager->GetDelegate()->Shutdown();
    manager->SetDelegate(test_delegate_.get());
    test_delegate_->SetDownloadManager(manager);

    embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
        &content::SlowDownloadHttpResponse::HandleSlowDownloadRequest));
    ASSERT_TRUE(embedded_test_server()->Start());
  }

  void SetDownloadBehavior(const std::string& behavior) {
    base::Value::Dict params;
    params.Set("behavior", behavior);
    SendCommandSync("Page.setDownloadBehavior", std::move(params));

    EXPECT_GE(received_responses_count(), 1);
  }

  void SetDownloadBehavior(const std::string& behavior,
                           const std::string& download_path) {
    base::Value::Dict params;
    params.Set("behavior", behavior);
    params.Set("downloadPath", download_path);
    SendCommandSync("Page.setDownloadBehavior", std::move(params));

    EXPECT_GE(received_responses_count(), 1);
  }

  // Create a DownloadTestObserverTerminal that will wait for the
  // specified number of downloads to finish.
  DownloadTestObserver* CreateWaiter(Shell* shell, int num_downloads) {
    DownloadManager* download_manager = DownloadManagerForShell(shell);
    return new DownloadTestObserverTerminal(
        download_manager, num_downloads,
        DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
  }

  // Note: Cannot be used with other alternative DownloadFileFactorys
  void SetupEnsureNoPendingDownloads() {
    DownloadManagerForShell(shell())->SetDownloadFileFactoryForTesting(
        std::unique_ptr<download::DownloadFileFactory>(
            new CountingDownloadFileFactory()));
  }

  void WaitForCompletion(download::DownloadItem* download) {
    DownloadUpdatedObserver(
        download, base::BindRepeating(&IsDownloadInState,
                                      download::DownloadItem::COMPLETE))
        .WaitForEvent();
  }

  bool EnsureNoPendingDownloads() {
    return CountingDownloadFile::GetNumberActiveFilesFromFileThread() == 0;
  }

  // Checks that |path| is has |file_size| bytes, and matches the |value|
  // string.
  bool VerifyFile(const base::FilePath& path,
                  const std::string& value,
                  const int64_t file_size) {
    std::string file_contents;

    {
      base::ScopedAllowBlockingForTesting allow_blocking;
      bool read = base::ReadFileToString(path, &file_contents);
      EXPECT_TRUE(read) << "Failed reading file: " << path.value() << std::endl;
      if (!read)
        return false;  // Couldn't read the file.
    }

    // Note: we don't handle really large files (more than size_t can hold)
    // so we will fail in that case.
    size_t expected_size = static_cast<size_t>(file_size);

    // Check the size.
    EXPECT_EQ(expected_size, file_contents.size());
    if (expected_size != file_contents.size())
      return false;

    // Check the contents.
    EXPECT_EQ(value, file_contents);
    if (UNSAFE_TODO(
            memcmp(file_contents.c_str(), value.c_str(), expected_size)) != 0) {
      return false;
    }

    return true;
  }

  // Start a download and return the item.
  download::DownloadItem* StartDownloadAndReturnItem(Shell* shell, GURL url) {
    std::unique_ptr<DownloadCreateObserver> observer(
        new DownloadCreateObserver(DownloadManagerForShell(shell)));
    shell->LoadURL(url);
    return observer->WaitForFinished();
  }

 private:
  // Location of the downloads directory for these tests
  base::ScopedTempDir downloads_directory_;
  std::unique_ptr<ShellDownloadManagerDelegate> test_delegate_;
};

}  // namespace

// Check that downloading a single file works.
IN_PROC_BROWSER_TEST_F(DevToolsDownloadContentTest, SingleDownload) {
  base::ScopedAllowBlockingForTesting allow_blocking;
  base::ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  std::string download_path =
      temp_dir.GetPath().AppendASCII("download").AsUTF8Unsafe();

  SetupEnsureNoPendingDownloads();
  NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
  Attach();

  SetDownloadBehavior("allow", download_path);
  // Create a download, wait until it's started, and confirm
  // we're in the expected state.
  download::DownloadItem* download = StartDownloadAndReturnItem(
      shell(), embedded_test_server()->GetURL("/download/download-test.lib"));
  ASSERT_EQ(download::DownloadItem::IN_PROGRESS, download->GetState());
  WaitForCompletion(download);
  ASSERT_EQ(download::DownloadItem::COMPLETE, download->GetState());
}

// Check that downloads can be cancelled gracefully.
IN_PROC_BROWSER_TEST_F(DevToolsDownloadContentTest, DownloadCancelled) {
  base::ScopedAllowBlockingForTesting allow_blocking;
  SetupEnsureNoPendingDownloads();
  NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
  Attach();

  SetDownloadBehavior("allow", "download");
  // Create a download, wait until it's started, and confirm
  // we're in the expected state.
  download::DownloadItem* download = StartDownloadAndReturnItem(
      shell(), embedded_test_server()->GetURL(
                   content::SlowDownloadHttpResponse::kUnknownSizeUrl));
  ASSERT_EQ(download::DownloadItem::IN_PROGRESS, download->GetState());

  // Cancel the download and wait for download system quiesce.
  download->Cancel(true);
  DownloadTestFlushObserver flush_observer(DownloadManagerForShell(shell()));
  flush_observer.WaitForFlush();

  // Get the important info from other threads and check it.
  EXPECT_TRUE(EnsureNoPendingDownloads());
}

// Check that denying downloads works.
IN_PROC_BROWSER_TEST_F(DevToolsDownloadContentTest, DeniedDownload) {
  base::ScopedAllowBlockingForTesting allow_blocking;
  SetupEnsureNoPendingDownloads();
  NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
  Attach();

  SetDownloadBehavior("deny");
  // Create a download, wait and confirm it was cancelled.
  download::DownloadItem* download = StartDownloadAndReturnItem(
      shell(), embedded_test_server()->GetURL("/download/download-test.lib"));
  DownloadTestFlushObserver flush_observer(DownloadManagerForShell(shell()));
  flush_observer.WaitForFlush();
  EXPECT_TRUE(EnsureNoPendingDownloads());
  ASSERT_EQ(download::DownloadItem::CANCELLED, download->GetState());
}

// Check that defaulting downloads works as expected.
IN_PROC_BROWSER_TEST_F(DevToolsDownloadContentTest, DefaultDownload) {
  base::ScopedAllowBlockingForTesting allow_blocking;
  SetupEnsureNoPendingDownloads();
  NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
  Attach();

  SetDownloadBehavior("default");
  // Create a download, wait until it's started, and confirm
  // we're in the expected state.
  download::DownloadItem* download = StartDownloadAndReturnItem(
      shell(), embedded_test_server()->GetURL(
                   content::SlowDownloadHttpResponse::kUnknownSizeUrl));
  ASSERT_EQ(download::DownloadItem::IN_PROGRESS, download->GetState());

  // Cancel the download and wait for download system quiesce.
  download->Cancel(true);
  DownloadTestFlushObserver flush_observer(DownloadManagerForShell(shell()));
  flush_observer.WaitForFlush();

  // Get the important info from other threads and check it.
  EXPECT_TRUE(EnsureNoPendingDownloads());
}

// Check that defaulting downloads cancels when there's no proxy
// download delegate.
IN_PROC_BROWSER_TEST_F(DevToolsDownloadContentTest, DefaultDownloadHeadless) {
  base::ScopedAllowBlockingForTesting allow_blocking;
  SetupEnsureNoPendingDownloads();
  NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
  Attach();
  RemoveShellDelegate(shell());

  SetDownloadBehavior("default");
  // Create a download, wait and confirm it was cancelled.
  download::DownloadItem* download = StartDownloadAndReturnItem(
      shell(), embedded_test_server()->GetURL("/download/download-test.lib"));
  DownloadTestFlushObserver flush_observer(DownloadManagerForShell(shell()));
  flush_observer.WaitForFlush();
  EXPECT_TRUE(EnsureNoPendingDownloads());
  ASSERT_EQ(download::DownloadItem::CANCELLED, download->GetState());
}

// Check that defaulting downloads cancels when there's no proxy
// download delegate.
IN_PROC_BROWSER_TEST_F(DevToolsDownloadContentTest,
                       SetDownloadBehaviorAccessChecks) {
  SetMayWriteLocalFiles(false);
  Attach();
  base::ScopedAllowBlockingForTesting allow_blocking;
  base::ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());

  base::Value::Dict params;
  params.Set("behavior", "allow");
  params.Set("downloadPath",
             temp_dir.GetPath().AppendASCII("download").AsUTF8Unsafe());

  SendCommandSync("Page.setDownloadBehavior", params.Clone());
  ASSERT_TRUE(error());
  EXPECT_EQ(*error()->FindString("message"), "Not allowed");
  Detach();
  SetMayWriteLocalFiles(true);
  Attach();
  SendCommandSync("Page.setDownloadBehavior", std::move(params));
  EXPECT_FALSE(error());
}

// Flaky on ChromeOS https://crbug.com/860312
// Also flaky on Wndows and other platforms: http://crbug.com/1070302
// Check that downloading multiple (in this case, 2) files does not result in
// corrupted files.
IN_PROC_BROWSER_TEST_F(DevToolsDownloadContentTest, DISABLED_MultiDownload) {
  base::ScopedAllowBlockingForTesting allow_blocking;
  base::ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  std::string download1_path =
      temp_dir.GetPath().AppendASCII("download1").AsUTF8Unsafe();
  std::string download2_path =
      temp_dir.GetPath().AppendASCII("download2").AsUTF8Unsafe();

  SetupEnsureNoPendingDownloads();
  NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
  Attach();

  SetDownloadBehavior("allow", download1_path);
  // Create a download, wait until it's started, and confirm
  // we're in the expected state.
  download::DownloadItem* download1 = StartDownloadAndReturnItem(
      shell(), embedded_test_server()->GetURL(
                   content::SlowDownloadHttpResponse::kUnknownSizeUrl));
  ASSERT_EQ(download::DownloadItem::IN_PROGRESS, download1->GetState());

  NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
  SetDownloadBehavior("allow", download2_path);
  // Start the second download and wait until it's done.
  GURL url(embedded_test_server()->GetURL("/download/download-test.lib"));
  download::DownloadItem* download2 = StartDownloadAndReturnItem(shell(), url);
  WaitForCompletion(download2);

  ASSERT_EQ(download::DownloadItem::IN_PROGRESS, download1->GetState());
  ASSERT_EQ(download::DownloadItem::COMPLETE, download2->GetState());

  // Allow the first request to finish.
  std::unique_ptr<DownloadTestObserver> observer2(CreateWaiter(shell(), 1));
  EXPECT_TRUE(NavigateToURL(
      shell(), embedded_test_server()->GetURL(
                   content::SlowDownloadHttpResponse::kFinishSlowResponseUrl)));
  observer2->WaitForFinished();  // Wait for the third request.
  EXPECT_EQ(
      1u, observer2->NumDownloadsSeenInState(download::DownloadItem::COMPLETE));

  // Get the important info from other threads and check it.
  EXPECT_TRUE(EnsureNoPendingDownloads());

  // The |DownloadItem|s should now be done and have the final file names.
  // Verify that the files have the expected data and size.
  // |file1| should be full of '*'s, and |file2| should be the same as the
  // source file.
  base::FilePath file1(download1->GetTargetFilePath());
  ASSERT_EQ(file1.DirName().MaybeAsASCII(), download1_path);
  size_t file_size1 =
      content::SlowDownloadHttpResponse::kFirstResponsePartSize +
      content::SlowDownloadHttpResponse::kSecondResponsePartSize;
  std::string expected_contents(file_size1, '*');
  ASSERT_TRUE(VerifyFile(file1, expected_contents, file_size1));

  base::FilePath file2(download2->GetTargetFilePath());
  ASSERT_EQ(file2.DirName().MaybeAsASCII(), download2_path);
  ASSERT_TRUE(base::ContentsEqual(
      file2, GetTestFilePath("download", "download-test.lib")));
}
#endif  // !defined(ANDROID)

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, UnsafeOperations) {
  NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
  Attach();

  base::Value::Dict params;
  params.Set("url", "http://www.example.com/hello.js");
  params.Set("data", "Tm90aGluZyB0byBzZWUgaGVyZSE=");

  SendCommandSync("Page.addCompilationCache", params.Clone());
  EXPECT_TRUE(result());
  Detach();
  SetAllowUnsafeOperations(false);
  Attach();
  SendCommandSync("Page.addCompilationCache", params.Clone());
  EXPECT_THAT(
      error()->FindInt("code"),
      testing::Optional(static_cast<int>(crdtp::DispatchCode::SERVER_ERROR)));
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, TracingWithPerfettoConfig) {
  base::trace_event::TraceConfig chrome_config;
  perfetto::TraceConfig perfetto_config;
  std::string perfetto_config_encoded;

  chrome_config = base::trace_event::TraceConfig();
  perfetto_config =
      tracing::GetDefaultPerfettoConfig(chrome_config,
                                        /*privacy_filtering_enabled=*/false,
                                        /*convert_to_legacy_json=*/false);
  perfetto_config_encoded =
      base::Base64Encode(perfetto_config.SerializeAsString());

  base::Value::Dict params;
  params.Set("perfettoConfig", perfetto_config_encoded);
  params.Set("transferMode", "ReturnAsStream");

  NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
  Attach();

  EXPECT_TRUE(SendCommandSync("Tracing.start", std::move(params)));
  EXPECT_TRUE(SendCommandSync("Tracing.end"));

  WaitForNotification("Tracing.tracingComplete", true);
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, NavigateToAboutBlankLoaderId) {
  NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
  Attach();

  base::Value::Dict params;
  params.Set("url", "about:blank");
  const base::Value::Dict* result =
      SendCommandSync("Page.navigate", std::move(params));
  EXPECT_THAT(result->FindString("loaderId"),
              testing::Pointee(testing::Not("")));
}

class SystemTracingDevToolsProtocolTest : public DevToolsProtocolTest {
 protected:
  const base::Value::Dict* StartSystemTrace() {
    perfetto::TraceConfig perfetto_config =
        tracing::GetDefaultPerfettoConfig(base::trace_event::TraceConfig(),
                                          /*privacy_filtering_enabled=*/false,
                                          /*convert_to_legacy_json=*/false);

    std::string perfetto_config_encoded =
        base::Base64Encode(perfetto_config.SerializeAsString());

    base::Value::Dict params;
    params.Set("perfettoConfig", perfetto_config_encoded);
    params.Set("transferMode", "ReturnAsStream");
    params.Set("tracingBackend", "system");

    NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
    Attach();

    return SendCommandSync("Tracing.start", std::move(params));
  }
};

IN_PROC_BROWSER_TEST_F(SystemTracingDevToolsProtocolTest,
                       StartSystemTracingFailsWhenSystemConsumerDisabled) {
  EXPECT_FALSE(StartSystemTrace());
}

#if BUILDFLAG(IS_POSIX)
class PosixSystemTracingDevToolsProtocolTest
    : public SystemTracingDevToolsProtocolTest {
 public:
  PosixSystemTracingDevToolsProtocolTest() {
    feature_list_.InitAndEnableFeature(features::kEnablePerfettoSystemTracing);
    tracing::PerfettoTracedProcess::SetAllowSystemTracingConsumerForTesting(
        true);
    const char* producer_sock = getenv("PERFETTO_PRODUCER_SOCK_NAME");
    saved_producer_sock_name_ = producer_sock ? producer_sock : std::string();
    const char* consumer_sock = getenv("PERFETTO_CONSUMER_SOCK_NAME");
    saved_consumer_sock_name_ = consumer_sock ? consumer_sock : std::string();
  }

  ~PosixSystemTracingDevToolsProtocolTest() override {
    if (!saved_producer_sock_name_.empty()) {
      SetProducerSockEnvName(saved_producer_sock_name_);
    } else {
      EXPECT_EQ(0, unsetenv("PERFETTO_PRODUCER_SOCK_NAME"));
    }
    if (!saved_consumer_sock_name_.empty()) {
      SetConsumerSockEnvName(saved_consumer_sock_name_);
    } else {
      EXPECT_EQ(0, unsetenv("PERFETTO_CONSUMER_SOCK_NAME"));
    }
  }

 protected:
  void SetProducerSockEnvName(const std::string& value) {
    ASSERT_EQ(0, setenv("PERFETTO_PRODUCER_SOCK_NAME", value.c_str(),
                        /*overwrite=*/true));
  }
  void SetConsumerSockEnvName(const std::string& value) {
    ASSERT_EQ(0, setenv("PERFETTO_CONSUMER_SOCK_NAME", value.c_str(),
                        /*overwrite=*/true));
  }

 private:
  base::test::ScopedFeatureList feature_list_;
  std::string saved_producer_sock_name_;
  std::string saved_consumer_sock_name_;
};

class InvalidSystemTracingDevToolsProtocolTest
    : public PosixSystemTracingDevToolsProtocolTest {
 public:
  void SetUp() override {
    // Use a non-existing backend.
    SetProducerSockEnvName("non_existing");
    SetConsumerSockEnvName("non_existing");

    PosixSystemTracingDevToolsProtocolTest::SetUp();
  }
};

// TODO(https://crbug.com/328350104): Fails ASAN builds
#if defined(ADDRESS_SANITIZER)
#define MAYBE_StartTracingFailsWithInvalidSockets \
  DISABLED_StartTracingFailsWithInvalidSockets
#else
#define MAYBE_StartTracingFailsWithInvalidSockets \
  StartTracingFailsWithInvalidSockets
#endif
IN_PROC_BROWSER_TEST_F(InvalidSystemTracingDevToolsProtocolTest,
                       MAYBE_StartTracingFailsWithInvalidSockets) {
  EXPECT_FALSE(StartSystemTrace());
}

class FakeSystemTracingDevToolsProtocolTest
    : public PosixSystemTracingDevToolsProtocolTest {
 public:
  FakeSystemTracingDevToolsProtocolTest()
      : deferred_task_runner_(new base::DeferredSequencedTaskRunner()) {}

  void SetUp() override {
    SetupService();
    PosixSystemTracingDevToolsProtocolTest::SetUp();
  }

  void PreRunTestOnMainThread() override {
    deferred_task_runner_->StartWithTaskRunner(
        base::SequencedTaskRunner::GetCurrentDefault());

    PosixSystemTracingDevToolsProtocolTest::PreRunTestOnMainThread();
  }

 private:
  void SetupService() {
    base::ScopedAllowBlockingForTesting allow_blocking;
    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());

    system_service_ = std::make_unique<tracing::MockSystemService>(
        temp_dir_, std::make_unique<base::tracing::PerfettoTaskRunner>(
                       deferred_task_runner_));

    SetProducerSockEnvName(system_service_->producer());
    SetConsumerSockEnvName(system_service_->consumer());
  }

  base::ScopedTempDir temp_dir_;
  scoped_refptr<base::DeferredSequencedTaskRunner> deferred_task_runner_;
  std::unique_ptr<tracing::MockSystemService> system_service_;
};

// No system consumer support on Android to reduce Chrome binary size.
#if BUILDFLAG(IS_ANDROID)
#define MAYBE_TracingWithFakeSystemBackend DISABLED_TracingWithFakeSystemBackend
#else
#define MAYBE_TracingWithFakeSystemBackend TracingWithFakeSystemBackend
#endif
IN_PROC_BROWSER_TEST_F(FakeSystemTracingDevToolsProtocolTest,
                       MAYBE_TracingWithFakeSystemBackend) {
  EXPECT_TRUE(StartSystemTrace());
  EXPECT_TRUE(SendCommandSync("Tracing.end"));
  WaitForNotification("Tracing.tracingComplete", true);
}

class FakeSystemTracingForbiddenDevToolsProtocolTest
    : public PosixSystemTracingDevToolsProtocolTest {
 public:
  void SetUp() override {
    tracing::PerfettoTracedProcess::SetAllowSystemTracingConsumerForTesting(
        false);
    PosixSystemTracingDevToolsProtocolTest::SetUp();
  }
};

// No system consumer support on Android to reduce Chrome binary size.
#if BUILDFLAG(IS_ANDROID)
#define MAYBE_SystemConsumerForbidden DISABLED_SystemConsumerForbidden
#else
#define MAYBE_SystemConsumerForbidden SystemConsumerForbidden
#endif
IN_PROC_BROWSER_TEST_F(FakeSystemTracingForbiddenDevToolsProtocolTest,
                       MAYBE_SystemConsumerForbidden) {
  EXPECT_FALSE(StartSystemTrace());
}
#endif  // BUILDFLAG(IS_POSIX)

class NetworkResponseProtocolTest : public DevToolsProtocolTest {
 protected:
  base::Value::Dict FetchAndWaitForResponse(const GURL& url) {
    WebContents* web_contents = shell()->web_contents();
    std::string script = JsReplace("fetch($1).then(r => r.status)", url.spec());
    EvalJsResult status = EvalJs(web_contents, script);
    CHECK_EQ(200, status);

    // Look for the requestId.
    auto matches_url = [](const GURL& url, const base::Value::Dict& params) {
      const std::string* got_url = params.FindStringByDottedPath("request.url");
      return got_url && *got_url == url.spec();
    };
    base::Value::Dict request = WaitForMatchingNotification(
        "Network.requestWillBeSent", base::BindRepeating(matches_url, url));
    const std::string* request_id = request.FindString("requestId");
    CHECK(request_id) << "Could not find request ID";

    // Look for the response.
    auto matches_id = [](const std::string& request_id,
                         const base::Value::Dict& params) {
      const std::string* id = params.FindString("requestId");
      return id && *id == request_id;
    };
    return WaitForMatchingNotification(
        "Network.responseReceived",
        base::BindRepeating(matches_id, *request_id));
  }
};

// Test that the SecurityDetails field of the resource response matches the
// server.
IN_PROC_BROWSER_TEST_F(NetworkResponseProtocolTest, SecurityDetails) {
  // Configure a specific TLS configuration to compare against.
  net::SSLServerConfig server_config;
  server_config.version_min = net::SSL_PROTOCOL_VERSION_TLS1_2;
  server_config.version_max = net::SSL_PROTOCOL_VERSION_TLS1_2;
  // TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
  server_config.cipher_suite_for_testing = 0xc02b;
  server_config.curves_for_testing = {NID_X25519};
  net::EmbeddedTestServer::ServerCertificateConfig cert_config;
  cert_config.signature_algorithm_for_testing = SSL_SIGN_ECDSA_SECP384R1_SHA384;
  net::EmbeddedTestServer server(net::EmbeddedTestServer::TYPE_HTTPS);
  server.SetSSLConfig(cert_config, server_config);
  server.ServeFilesFromSourceDirectory(GetTestDataFilePath());
  ASSERT_TRUE(server.Start());

  NavigateToURLBlockUntilNavigationsComplete(shell(),
                                             server.GetURL("/title1.html"), 1);

  Attach();
  SendCommandAsync("Network.enable");

  base::Value::Dict response =
      FetchAndWaitForResponse(server.GetURL("/empty.html"));

  const std::string* protocol =
      response.FindStringByDottedPath("response.securityDetails.protocol");
  ASSERT_TRUE(protocol);
  EXPECT_EQ("TLS 1.2", *protocol);

  const std::string* key_exchange =
      response.FindStringByDottedPath("response.securityDetails.keyExchange");
  ASSERT_TRUE(key_exchange);
  EXPECT_EQ("ECDHE_ECDSA", *key_exchange);

  const std::string* cipher =
      response.FindStringByDottedPath("response.securityDetails.cipher");
  ASSERT_TRUE(cipher);
  EXPECT_EQ("AES_128_GCM", *cipher);

  // AEAD ciphers should not report a MAC.
  EXPECT_FALSE(response.FindStringByDottedPath("response.securityDetails.mac"));

  const std::string* group = response.FindStringByDottedPath(
      "response.securityDetails.keyExchangeGroup");
  ASSERT_TRUE(group);
  EXPECT_EQ("X25519", *group);

  std::optional<int> sigalg = response.FindIntByDottedPath(
      "response.securityDetails.serverSignatureAlgorithm");
  EXPECT_EQ(SSL_SIGN_ECDSA_SECP384R1_SHA384, sigalg);

  std::optional<bool> ech = response.FindBoolByDottedPath(
      "response.securityDetails.encryptedClientHello");
  EXPECT_EQ(false, ech);

  const std::string* subject =
      response.FindStringByDottedPath("response.securityDetails.subjectName");
  ASSERT_TRUE(subject);
  EXPECT_EQ(server.GetCertificate()->subject().common_name, *subject);

  const std::string* issuer =
      response.FindStringByDottedPath("response.securityDetails.issuer");
  ASSERT_TRUE(issuer);
  EXPECT_EQ(server.GetCertificate()->issuer().common_name, *issuer);

  // The default certificate has a single SAN, 127.0.0.1.
  const base::Value* sans =
      response.FindByDottedPath("response.securityDetails.sanList");
  ASSERT_TRUE(sans);
  ASSERT_EQ(1u, sans->GetList().size());
  EXPECT_EQ(base::Value("127.0.0.1"), sans->GetList()[0]);

  std::optional<double> valid_from =
      response.FindDoubleByDottedPath("response.securityDetails.validFrom");
  EXPECT_EQ(server.GetCertificate()->valid_start().InSecondsFSinceUnixEpoch(),
            valid_from);

  std::optional<double> valid_to =
      response.FindDoubleByDottedPath("response.securityDetails.validTo");
  EXPECT_EQ(server.GetCertificate()->valid_expiry().InSecondsFSinceUnixEpoch(),
            valid_to);
}

// Test SecurityDetails, but with a TLS 1.3 cipher suite, which should not
// report a key exchange component.
IN_PROC_BROWSER_TEST_F(NetworkResponseProtocolTest, SecurityDetailsTLS13) {
  // Configure a specific TLS configuration to compare against.
  net::SSLServerConfig server_config;
  server_config.version_min = net::SSL_PROTOCOL_VERSION_TLS1_3;
  server_config.version_max = net::SSL_PROTOCOL_VERSION_TLS1_3;
  server_config.curves_for_testing = {NID_X25519};
  net::EmbeddedTestServer::ServerCertificateConfig cert_config;
  cert_config.signature_algorithm_for_testing = SSL_SIGN_ECDSA_SECP256R1_SHA256;
  net::EmbeddedTestServer server(net::EmbeddedTestServer::TYPE_HTTPS);
  server.SetSSLConfig(cert_config, server_config);
  server.ServeFilesFromSourceDirectory(GetTestDataFilePath());
  ASSERT_TRUE(server.Start());

  NavigateToURLBlockUntilNavigationsComplete(shell(),
                                             server.GetURL("/title1.html"), 1);

  Attach();
  SendCommandAsync("Network.enable");

  base::Value::Dict response =
      FetchAndWaitForResponse(server.GetURL("/empty.html"));

  const std::string* protocol =
      response.FindStringByDottedPath("response.securityDetails.protocol");
  ASSERT_TRUE(protocol);
  EXPECT_EQ("TLS 1.3", *protocol);

  const std::string* key_exchange =
      response.FindStringByDottedPath("response.securityDetails.keyExchange");
  ASSERT_TRUE(key_exchange);
  EXPECT_EQ("", *key_exchange);

  const std::string* cipher =
      response.FindStringByDottedPath("response.securityDetails.cipher");
  ASSERT_TRUE(cipher);
  // Depending on whether the host machine has AES hardware, the server may
  // pick AES-GCM or ChaCha20-Poly1305.
  EXPECT_TRUE(*cipher == "AES_128_GCM" || *cipher == "CHACHA20_POLY1305");

  // AEAD ciphers should not report a MAC.
  EXPECT_FALSE(response.FindStringByDottedPath("response.securityDetails.mac"));

  const std::string* group = response.FindStringByDottedPath(
      "response.securityDetails.keyExchangeGroup");
  ASSERT_TRUE(group);
  EXPECT_EQ("X25519", *group);

  std::optional<int> sigalg = response.FindIntByDottedPath(
      "response.securityDetails.serverSignatureAlgorithm");
  EXPECT_EQ(SSL_SIGN_ECDSA_SECP256R1_SHA256, sigalg);

  std::optional<bool> ech = response.FindBoolByDottedPath(
      "response.securityDetails.encryptedClientHello");
  EXPECT_EQ(false, ech);
}

// Test SecurityDetails, but with a legacy cipher suite, which should report a
// separate MAC component and no group.
IN_PROC_BROWSER_TEST_F(NetworkResponseProtocolTest,
                       SecurityDetailsLegacyCipher) {
  // Configure a specific TLS configuration to compare against.
  net::SSLServerConfig server_config;
  server_config.version_min = net::SSL_PROTOCOL_VERSION_TLS1_2;
  server_config.version_max = net::SSL_PROTOCOL_VERSION_TLS1_2;
  // TLS_RSA_WITH_AES_128_CBC_SHA
  server_config.cipher_suite_for_testing = 0x002f;
  net::EmbeddedTestServer server(net::EmbeddedTestServer::TYPE_HTTPS);
  server.SetSSLConfig(net::EmbeddedTestServer::ServerCertificate::CERT_OK,
                      server_config);
  server.ServeFilesFromSourceDirectory(GetTestDataFilePath());
  ASSERT_TRUE(server.Start());

  NavigateToURLBlockUntilNavigationsComplete(shell(),
                                             server.GetURL("/title1.html"), 1);

  Attach();
  SendCommandAsync("Network.enable");

  base::Value::Dict response =
      FetchAndWaitForResponse(server.GetURL("/empty.html"));

  const std::string* key_exchange =
      response.FindStringByDottedPath("response.securityDetails.keyExchange");
  ASSERT_TRUE(key_exchange);
  EXPECT_EQ("RSA", *key_exchange);

  const std::string* cipher =
      response.FindStringByDottedPath("response.securityDetails.cipher");
  ASSERT_TRUE(cipher);
  EXPECT_EQ("AES_128_CBC", *cipher);

  const std::string* mac =
      response.FindStringByDottedPath("response.securityDetails.mac");
  ASSERT_TRUE(mac);
  EXPECT_EQ("HMAC-SHA1", *mac);

  // RSA ciphers should not report a MAC.
  EXPECT_FALSE(response.FindStringByDottedPath(
      "response.securityDetails.keyExchangeGroup"));
}

// Test that complex certificate SAN lists are reported in SecurityDetails.
IN_PROC_BROWSER_TEST_F(NetworkResponseProtocolTest, SecurityDetailsSAN) {
  net::EmbeddedTestServer::ServerCertificateConfig cert_config;
  cert_config.dns_names = {"a.example", "b.example", "*.c.example"};
  cert_config.ip_addresses = {net::IPAddress::IPv4Localhost(),
                              net::IPAddress::IPv6Localhost(),
                              net::IPAddress(1, 2, 3, 4)};
  net::EmbeddedTestServer server(net::EmbeddedTestServer::TYPE_HTTPS);
  server.SetSSLConfig(cert_config);
  server.ServeFilesFromSourceDirectory(GetTestDataFilePath());
  ASSERT_TRUE(server.Start());

  NavigateToURLBlockUntilNavigationsComplete(shell(),
                                             server.GetURL("/title1.html"), 1);

  Attach();
  SendCommandAsync("Network.enable");

  base::Value::Dict response =
      FetchAndWaitForResponse(server.GetURL("/empty.html"));
  const base::Value* sans =
      response.FindByDottedPath("response.securityDetails.sanList");
  ASSERT_TRUE(sans);
  ASSERT_EQ(6u, sans->GetList().size());
  EXPECT_EQ(base::Value("a.example"), sans->GetList()[0]);
  EXPECT_EQ(base::Value("b.example"), sans->GetList()[1]);
  EXPECT_EQ(base::Value("*.c.example"), sans->GetList()[2]);
  EXPECT_EQ(base::Value("127.0.0.1"), sans->GetList()[3]);
  EXPECT_EQ(base::Value("::1"), sans->GetList()[4]);
  EXPECT_EQ(base::Value("1.2.3.4"), sans->GetList()[5]);
}

class NetworkResponseProtocolECHTest : public NetworkResponseProtocolTest {
 public:
  // a.test is covered by `CERT_TEST_NAMES`.
  static constexpr char kHostname[] = "a.test";
  static constexpr char kPublicName[] = "public-name.test";
  static constexpr char kDohServerHostname[] = "doh.test";

  NetworkResponseProtocolECHTest()
      : ech_server_{net::EmbeddedTestServer::TYPE_HTTPS} {
    scoped_feature_list_.InitWithFeaturesAndParameters(
        /*enabled_features=*/
        {{net::features::kUseDnsHttpsSvcb,
          {{"UseDnsHttpsSvcbEnforceSecureResponse", "true"}}}},
        /*disabled_features=*/{});
  }

  void SetUpOnMainThread() override {
    // Configure `ech_server_` to use ECH.
    net::SSLServerConfig server_config;
    std::vector<uint8_t> ech_config_list;
    server_config.ech_keys = net::MakeTestEchKeys(
        kPublicName, /*max_name_len=*/64, &ech_config_list);
    ASSERT_TRUE(server_config.ech_keys);
    ech_server_.ServeFilesFromSourceDirectory(GetTestDataFilePath());
    ech_server_.SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES,
                             server_config);

    ASSERT_TRUE(ech_server_.Start());

    // Start a DoH server, which ensures we use a resolver with HTTPS RR
    // support. Configure it to serve records for `ech_server_`.
    doh_server_.SetHostname(kDohServerHostname);
    url::SchemeHostPort ech_host(GetURL("/"));
    doh_server_.AddAddressRecord(ech_host.host(),
                                 net::IPAddress::IPv4Localhost());
    doh_server_.AddRecord(net::BuildTestHttpsServiceRecord(
        net::dns_util::GetNameForHttpsQuery(ech_host),
        /*priority=*/1, /*service_name=*/ech_host.host(),
        {net::BuildTestHttpsServiceEchConfigParam(ech_config_list)}));
    ASSERT_TRUE(doh_server_.Start());

    // Add a single bootstrapping rule so we can resolve the DoH server.
    host_resolver()->AddRule(kDohServerHostname, "127.0.0.1");

    // Configure the network service to use the test DoH server.
    std::optional<net::DnsOverHttpsConfig> doh_config =
        net::DnsOverHttpsConfig::FromString(doh_server_.GetTemplate());
    ASSERT_TRUE(doh_config.has_value());
    SetTestDohConfig(net::SecureDnsMode::kSecure,
                     std::move(doh_config.value()));
    SetReplaceSystemDnsConfig();
  }

  GURL GetURL(std::string_view path) {
    return ech_server_.GetURL(kHostname, path);
  }

 private:
  base::test::ScopedFeatureList scoped_feature_list_;
  net::TestDohServer doh_server_;
  net::EmbeddedTestServer ech_server_;
};

// Test SecurityDetails reports when Encrypted ClientHello was negotiated.
// Flaky: https://crbug.com/1521189
IN_PROC_BROWSER_TEST_F(NetworkResponseProtocolECHTest,
                       DISABLED_SecurityDetailsECH) {
  NavigateToURLBlockUntilNavigationsComplete(shell(), GetURL("/title1.html"),
                                             1);

  Attach();
  SendCommandAsync("Network.enable");

  base::Value::Dict response = FetchAndWaitForResponse(GetURL("/empty.html"));
  std::optional<bool> ech = response.FindBoolByDottedPath(
      "response.securityDetails.encryptedClientHello");
  EXPECT_EQ(true, ech);
}

IN_PROC_BROWSER_TEST_F(
    PrerenderDevToolsProtocolTest,
    PrerenderStatusUpdatedReportsFailureWithDisallowedMojoInterface) {
  base::HistogramTester histogram_tester;
  ASSERT_TRUE(embedded_test_server()->Start());
  const GURL kInitialUrl = GetUrl("/empty.html");
  const GURL kPrerenderingUrl = GetUrl("/empty.html?prerender");

  // Navigate to an initial page.
  ASSERT_TRUE(NavigateToURL(shell(), kInitialUrl));

  // Make a prerendered page.
  FrameTreeNodeId host_id = AddPrerender(kPrerenderingUrl);
  auto* prerender_render_frame_host = GetPrerenderedMainFrameHost(host_id);
  Attach();
  SendCommandSync("Preload.enable");

  // Executing `navigator.getGamepads()` to start binding the GamepadMonitor
  // interface, and this is expected to cause prerender cancellation because
  // the API is disallowed.
  ExecuteScriptAsyncWithoutUserGesture(prerender_render_frame_host,
                                       "navigator.getGamepads()");

  base::Value::Dict result;
  while (true) {
    result = WaitForNotification("Preload.prerenderStatusUpdated", true);
    if (*result.FindString("status") == "Failure") {
      break;
    }
  }

  EXPECT_THAT(*result.FindString("disallowedMojoInterface"),
              Eq("device.mojom.GamepadMonitor"));
}

IN_PROC_BROWSER_TEST_F(
    PrerenderDevToolsProtocolTest,
    PrerenderStatusUpdatedReportsFailureWithPrerenderMismatchedHeaders) {
  const std::string user_agent_override = "foo";
  ASSERT_TRUE(embedded_test_server()->Start());
  // Navigate to an initial page.
  const GURL initial_url = GetUrl("/empty.html");
  ASSERT_TRUE(NavigateToURL(shell(), initial_url));

  // Enable user agent override for future navigations.
  UserAgentInjector injector(shell()->web_contents(), user_agent_override);

  const GURL prerendering_url = GetUrl("/empty.html?prerender");

  // Start prerendering.
  const FrameTreeNodeId host_id = AddPrerender(prerendering_url);

  Attach();
  SendCommandSync("Preload.enable");

  RenderFrameHostImpl* prerender_rfh =
      static_cast<RenderFrameHostImpl*>(GetPrerenderedMainFrameHost(host_id));
  EXPECT_EQ(user_agent_override, EvalJs(prerender_rfh, "navigator.userAgent"));

  // Stop overriding user agent from now on.
  injector.set_is_overriding_user_agent(false);

  // Activate the prerendered page.
  test::PrerenderHostObserver host_observer(*web_contents(), host_id);
  NavigatePrimaryPage(prerendering_url);
  host_observer.WaitForDestroyed();

  base::Value::Dict result;
  while (true) {
    result = WaitForNotification("Preload.prerenderStatusUpdated", true);
    if (*result.FindString("status") == "Failure") {
      break;
    }
  }
  EXPECT_TRUE(result.Find("mismatchedHeaders"));
}

IN_PROC_BROWSER_TEST_F(PrerenderDevToolsProtocolTest,
                       RenderFrameDevToolsAgentHostCacheEvictionCrash) {
  ASSERT_TRUE(embedded_test_server()->Start());
  const GURL kInitialUrl = GetUrl("/empty.html");
  const GURL kPrerenderingUrl = GetUrl("/empty.html?prerender");
  WebContentsImpl* web_contents_impl =
      static_cast<WebContentsImpl*>(web_contents());

  ASSERT_TRUE(NavigateToURL(shell(), kInitialUrl));

  // Attaching a session via a "tab" target is required to opt-in into
  // FTN swapping mode during prerender activation.
  AttachToTabTarget(web_contents_impl);
  base::Value::Dict command_params;
  command_params.Set("autoAttach", true);
  command_params.Set("waitForDebuggerOnStart", false);
  command_params.Set("flatten", true);
  SendCommandSync("Target.setAutoAttach", std::move(command_params));

  // Stash current RFDTAH for WebContents that is about to be retained
  // by BFCache after prerender navigation and flushed later.
  auto old_host = DevToolsAgentHost::GetOrCreateFor(web_contents_impl);
  RenderFrameDeletedObserver delete_observer(
      web_contents_impl->GetPrimaryMainFrame());

  // Activating a prerender should cause FTN swapping on the RFH and put
  // the old one into the BFCache with frame_tree_node_ == nullptr.
  AddPrerender(kPrerenderingUrl);
  NavigatePrimaryPage(kPrerenderingUrl);

  EXPECT_FALSE(delete_observer.deleted());
  web_contents_impl->GetController().GetBackForwardCache().Flush();
  delete_observer.WaitUntilDeleted();

  // Assure methods on disconnected host are safe to call.
  EXPECT_THAT(old_host->GetTitle(), testing::Eq(""));
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, ResponseAfterReload) {
  ASSERT_TRUE(embedded_test_server()->Start());
  GURL url = embedded_test_server()->GetURL("a.test", "/title1.html");

  NavigateToURLBlockUntilNavigationsComplete(shell(), url, 1);

  Attach();

  SendCommandSync("Fetch.enable");
  SendCommandAsync("Page.reload");

  base::Value::Dict command_params;
  command_params.Set("discover", true);
  SendCommandSync("Target.setDiscoverTargets", std::move(command_params));

  {
    content::ScopedAllowRendererCrashes scoped_allow_renderer_crashes;
    shell()->LoadURL(GURL(blink::kChromeUICrashURL));
    WaitForNotification("Target.targetCrashed", true);
  }

  SetProtocolCommandId(42);
  SendCommandAsync("Network.enable");

  SetProtocolCommandId(42);
  SendCommandSync("Page.reload");

  SendCommandAsync("Fetch.disable");
  SendCommandSync("Network.enable");
}

class SharedStorageDevToolsProtocolTest : public DevToolsProtocolTest {
 public:
  SharedStorageDevToolsProtocolTest() {
    feature_list_
        .InitWithFeaturesAndParameters(/*enabled_features=*/
                                       {{network::features::kSharedStorageAPI,
                                         {{"SharedStorageBitBudget",
                                           base::NumberToString(
                                               kBudgetAllowed)}}},
                                        {features::
                                             kPrivacySandboxAdsAPIsOverride,
                                         {}}},
                                       /*disabled_features=*/{});
  }

  void MakeBudgetWithdrawal(const GURL& url, double bits) {
    auto* manager = shell()
                        ->web_contents()
                        ->GetBrowserContext()
                        ->GetDefaultStoragePartition()
                        ->GetSharedStorageManager();
    ASSERT_TRUE(manager);
    base::test::TestFuture<storage::SharedStorageManager::OperationResult>
        future;
    manager->MakeBudgetWithdrawal(net::SchemefulSite(url), bits,
                                  future.GetCallback());
    EXPECT_EQ(storage::SharedStorageManager::OperationResult::kSuccess,
              future.Get());
  }

 private:
  base::test::ScopedFeatureList feature_list_;
};

IN_PROC_BROWSER_TEST_F(SharedStorageDevToolsProtocolTest,
                       ResetSharedStorageBudget) {
  ASSERT_TRUE(embedded_test_server()->Start());
  GURL url = embedded_test_server()->GetURL("a.test", "/title1.html");
  NavigateToURLBlockUntilNavigationsComplete(shell(), url, 1);
  Attach();

  base::Value::Dict command_params;
  command_params.Set("enable", true);
  SendCommandSync("Storage.setSharedStorageTracking",
                  std::move(command_params));
  ASSERT_FALSE(error());

  // Set an entry in order to initialize shared storage database for
  // `origin_str`.
  command_params = base::Value::Dict();
  std::string origin_str = url.GetWithEmptyPath().spec();
  command_params.Set("ownerOrigin", origin_str);
  command_params.Set("key", "key1");
  command_params.Set("value", "value1");
  SendCommandSync("Storage.setSharedStorageEntry", std::move(command_params));
  ASSERT_FALSE(error());

  // "remainingBudget" should currently be at its max, `kBudgetAllowed`.
  command_params = base::Value::Dict();
  command_params.Set("ownerOrigin", origin_str);
  SendCommandSync("Storage.getSharedStorageMetadata",
                  std::move(command_params));
  ASSERT_TRUE(result());
  EXPECT_THAT(result()->FindDoubleByDottedPath("metadata.remainingBudget"),
              testing::Optional(kBudgetAllowed));

  // Make some withdrawals.
  MakeBudgetWithdrawal(url, 1.0);
  MakeBudgetWithdrawal(url, 2.5);

  // "remainingBudget" should have decreased the appropriate amount.
  command_params = base::Value::Dict();
  command_params.Set("ownerOrigin", origin_str);
  SendCommandSync("Storage.getSharedStorageMetadata",
                  std::move(command_params));
  ASSERT_TRUE(result());
  EXPECT_THAT(result()->FindDoubleByDottedPath("metadata.remainingBudget"),
              testing::Optional(kBudgetAllowed - 1.0 - 2.5));

  // Reset the budget.
  command_params = base::Value::Dict();
  command_params.Set("ownerOrigin", origin_str);
  SendCommandSync("Storage.resetSharedStorageBudget",
                  std::move(command_params));
  ASSERT_FALSE(error());

  // "remainingBudget" should be back at its max, `kBudgetAllowed`.
  command_params = base::Value::Dict();
  command_params.Set("ownerOrigin", origin_str);
  SendCommandSync("Storage.getSharedStorageMetadata",
                  std::move(command_params));
  ASSERT_TRUE(result());
  EXPECT_THAT(result()->FindDoubleByDottedPath("metadata.remainingBudget"),
              testing::Optional(kBudgetAllowed));
}

IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, TestRawHeadersWithRedirects) {
  net::EmbeddedTestServer& https_test_server = embedded_https_test_server();
  https_test_server.AddDefaultHandlers();
  https_test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES);
  https_test_server.ServeFilesFromSourceDirectory(GetTestDataFilePath());
  ASSERT_TRUE(https_test_server.Start());
  ASSERT_TRUE(embedded_test_server()->Start());  // For first redirect.
  // Localhost does not support HSTS, so we must serve from "a.test" instead.
  GURL https_url = https_test_server.GetURL("a.test", "/hello.html");
  base::Time expiry = base::Time::Now() + base::Days(1000);
  bool include_subdomains = false;
  content::StoragePartition* partition = shell()
                                             ->web_contents()
                                             ->GetBrowserContext()
                                             ->GetDefaultStoragePartition();
  base::RunLoop run_loop;
  partition->GetNetworkContext()->AddHSTS(
      https_url.host(), expiry, include_subdomains, run_loop.QuitClosure());
  run_loop.Run();

  GURL::Replacements replace_scheme;
  replace_scheme.SetSchemeStr("http");
  GURL http_url = https_url.ReplaceComponents(replace_scheme);
  GURL redirect_url =
      embedded_test_server()->GetURL("/server-redirect?" + http_url.spec());

  NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
  Attach();
  SendCommandSync("Network.enable");

  base::Value::Dict params;
  params.Set("url", redirect_url.spec());
  SendCommandAsync("Page.navigate", std::move(params));

  {
    const base::Value::Dict orig_request =
        WaitForNotification("Network.requestWillBeSent", true);
    EXPECT_THAT(orig_request.FindStringByDottedPath("request.url"),
                Pointee(redirect_url));
    EXPECT_THAT(orig_request.FindDict("redirectResponse"), testing::IsNull());
  }
  {
    // The first redirect is a real, server-issued redirect:
    // http://127.0.0.1:N/server-redirect?http://a.test:M/hello.html =>
    // http://a.test:M/hello.html

    const base::Value::Dict redirected_request =
        WaitForNotification("Network.requestWillBeSent", true);
    EXPECT_THAT(redirected_request.FindStringByDottedPath("request.url"),
                Pointee(http_url));
    EXPECT_THAT(redirected_request.FindBool("redirectHasExtraInfo"),
                testing::Optional(true));
    EXPECT_THAT(
        redirected_request.FindIntByDottedPath("redirectResponse.status"),
        testing::Optional(301));
    EXPECT_THAT(redirected_request.FindStringByDottedPath(
                    "redirectResponse.headers.Location"),
                Pointee(http_url.spec()));
  }
  {
    // The second redirect is an interan HSTS redirect:
    // http://a.test:M/hello.html => https://a.test:M/hello.html
    const base::Value::Dict redirected_request =
        WaitForNotification("Network.requestWillBeSent", true);
    EXPECT_THAT(redirected_request.FindStringByDottedPath("request.url"),
                Pointee(https_url));
    EXPECT_THAT(redirected_request.FindBool("redirectHasExtraInfo"),
                testing::Optional(false));
    EXPECT_THAT(
        redirected_request.FindIntByDottedPath("redirectResponse.status"),
        testing::Optional(307));
    EXPECT_THAT(redirected_request.FindStringByDottedPath(
                    "redirectResponse.headers.Location"),
                Pointee(https_url.spec()));
  }

  // Nothing of interest to check for the request headers, except that the event
  // is there.
  WaitForNotification("Network.requestWillBeSentExtraInfo", true);

  {
    const base::Value::Dict response_extra_info =
        WaitForNotification("Network.responseReceivedExtraInfo", true);
    EXPECT_THAT(response_extra_info.FindIntByDottedPath("statusCode"),
                testing::Optional(301));
    EXPECT_THAT(response_extra_info.FindStringByDottedPath("headers.Location"),
                Pointee(http_url.spec()));
  }

  // Nothing of interest to check for the request headers, except that the event
  // is there.
  WaitForNotification("Network.requestWillBeSentExtraInfo", true);

  {
    const base::Value::Dict response_extra_info =
        WaitForNotification("Network.responseReceivedExtraInfo", true);
    EXPECT_THAT(response_extra_info.FindIntByDottedPath("statusCode"),
                testing::Optional(200));
    EXPECT_THAT(response_extra_info.FindStringByDottedPath("headers.Location"),
                testing::IsNull());
  }
  {
    const base::Value::Dict response_received =
        WaitForNotification("Network.responseReceived", true);
    EXPECT_THAT(response_received.FindBool("hasExtraInfo"),
                testing::Optional(true));
    EXPECT_THAT(response_received.FindIntByDottedPath("response.status"),
                testing::Optional(200));
    EXPECT_THAT(response_received.FindStringByDottedPath("response.statusText"),
                Pointee(std::string("OK")));
  }
}

}  // namespace content
