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

#include <stddef.h>

#include <deque>
#include <memory>

#include "base/cancelable_callback.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/location.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_timeouts.h"
#include "base/threading/thread_restrictions.h"
#include "base/values.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/browser_features.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/devtools/device/tcp_device_provider.h"
#include "chrome/browser/devtools/devtools_window_testing.h"
#include "chrome/browser/devtools/protocol/browser_handler.h"
#include "chrome/browser/extensions/api/developer_private/developer_private_api.h"
#include "chrome/browser/extensions/chrome_extension_test_notification_observer.h"
#include "chrome/browser/extensions/component_loader.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/extensions/extension_management_constants.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/extensions/unpacked_installer.h"
#include "chrome/browser/lifetime/application_lifetime_desktop.h"
#include "chrome/browser/lifetime/browser_shutdown.h"
#include "chrome/browser/policy/chrome_browser_policy_connector.h"
#include "chrome/browser/policy/developer_tools_policy_handler.h"
#include "chrome/browser/policy/profile_policy_connector.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/renderer_context_menu/render_view_context_menu.h"
#include "chrome/browser/sync/test/integration/sync_service_impl_harness.h"
#include "chrome/browser/sync/test/integration/sync_test.h"
#include "chrome/browser/ui/autofill/autofill_popup_controller_impl.h"
#include "chrome/browser/ui/autofill/chrome_autofill_client.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/extensions/extension_side_panel_test_utils.h"
#include "chrome/browser/ui/tabs/tab_enums.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/test_chrome_web_ui_controller_factory.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/autofill/content/browser/content_autofill_driver.h"
#include "components/autofill/content/browser/content_autofill_driver_factory.h"
#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/browser_autofill_manager.h"
#include "components/autofill/core/browser/browser_autofill_manager_test_delegate.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/javascript_dialogs/app_modal_dialog_controller.h"
#include "components/javascript_dialogs/app_modal_dialog_view.h"
#include "components/keep_alive_registry/keep_alive_registry.h"
#include "components/keep_alive_registry/keep_alive_types.h"
#include "components/language/core/browser/pref_names.h"
#include "components/policy/core/common/mock_configuration_policy_provider.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/policy_constants.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/url_data_source.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui_controller.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/hit_test_region_observer.h"
#include "content/public/test/scoped_web_ui_controller_factory_registration.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
#include "content/public/test/url_loader_interceptor.h"
#include "extensions/browser/api_test_utils.h"
#include "extensions/browser/extension_host_test_helper.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_registry_observer.h"
#include "extensions/browser/extension_system.h"
#include "extensions/browser/offscreen_document_host.h"
#include "extensions/browser/test_extension_registry_observer.h"
#include "extensions/common/extension_features.h"
#include "extensions/common/manifest.h"
#include "extensions/common/mojom/view_type.mojom.h"
#include "extensions/common/switches.h"
#include "extensions/test/extension_test_message_listener.h"
#include "extensions/test/test_extension_dir.h"
#include "mojo/public/cpp/bindings/sync_call_restrictions.h"
#include "net/base/filename_util.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/chrome_debug_urls.h"
#include "third_party/blink/public/common/input/web_input_event.h"
#include "ui/base/ui_base_switches.h"
#include "ui/compositor/compositor_switches.h"
#include "ui/gl/gl_switches.h"
#include "url/gurl.h"

using content::DevToolsAgentHost;
using content::DevToolsAgentHostObserver;
using content::NavigationController;
using content::RenderFrameHost;
using content::WebContents;
using extensions::Extension;
using javascript_dialogs::AppModalDialogView;

namespace {

const char kDebuggerTestPage[] = "/devtools/debugger_test_page.html";
const char kPauseWhenLoadingDevTools[] =
    "/devtools/pause_when_loading_devtools.html";
const char kPageWithContentScript[] = "/devtools/page_with_content_script.html";
const char kNavigateBackTestPage[] = "/devtools/navigate_back.html";
const char kWindowOpenTestPage[] = "/devtools/window_open.html";
const char kLatencyInfoTestPage[] = "/devtools/latency_info.html";
const char kChunkedTestPage[] = "/chunked";
const char kPushTestPage[] = "/devtools/push_test_page.html";
// The resource is not really pushed, but mock url request job pretends it is.
const char kPushTestResource[] = "/devtools/image.png";
const char kPushUseNullEndTime[] = "pushUseNullEndTime";
const char kSlowTestPage[] =
    "/chunked?waitBeforeHeaders=100&waitBetweenChunks=100&chunksNumber=2";
const char kSharedWorkerTestPage[] = "/workers/workers_ui_shared_worker.html";
const char kSharedWorkerTestWorker[] = "/workers/workers_ui_shared_worker.js";
const char kReloadSharedWorkerTestPage[] =
    "/workers/debug_shared_worker_initialization.html";
const char kReloadSharedWorkerTestWorker[] =
    "/workers/debug_shared_worker_initialization.js";
const char kEmulateNetworkConditionsPage[] =
    "/devtools/emulate_network_conditions.html";
const char kDispatchKeyEventShowsAutoFill[] =
    "/devtools/dispatch_key_event_shows_auto_fill.html";
const char kDOMWarningsTestPage[] = "/devtools/dom_warnings_page.html";
const char kEmptyTestPage[] = "/devtools/empty.html";
// Arbitrary page that returns a 200 response, for tests that don't care about
// more than that.
const char kArbitraryPage[] = "/title1.html";

template <typename... T>
void DispatchOnTestSuiteSkipCheck(DevToolsWindow* window,
                                  const char* method,
                                  T... args) {
  WebContents* wc = DevToolsWindowTesting::Get(window)->main_web_contents();
  const char* args_array[] = {method, args...};
  std::ostringstream script;
  script << "uiTests.dispatchOnTestSuite([";
  for (size_t i = 0; i < std::size(args_array); ++i) {
    script << (i ? "," : "") << '\"' << args_array[i] << '\"';
  }
  script << "])";

  content::DOMMessageQueue message_queue;
  EXPECT_TRUE(content::ExecJs(wc, script.str()));

  std::string result;
  EXPECT_TRUE(message_queue.WaitForMessage(&result));

  EXPECT_EQ("\"[OK]\"", result);
}

void LoadLegacyFilesInFrontend(DevToolsWindow* window) {
  WebContents* wc = DevToolsWindowTesting::Get(window)->main_web_contents();
  content::DOMMessageQueue message_queue;
  EXPECT_TRUE(content::ExecJs(wc, "uiTests.setupLegacyFilesForTest();",
                              content::EXECUTE_SCRIPT_NO_RESOLVE_PROMISES));

  std::string result;
  EXPECT_TRUE(message_queue.WaitForMessage(&result));

  ASSERT_EQ("\"[OK]\"", result);
}

template <typename... T>
void DispatchOnTestSuite(DevToolsWindow* window,
                         const char* method,
                         T... args) {
  WebContents* wc = DevToolsWindowTesting::Get(window)->main_web_contents();
  // At first check that JavaScript part of the front-end is loaded by
  // checking that global variable uiTests exists(it's created after all js
  // files have been loaded) and has runTest method.
  ASSERT_EQ(
      "function",
      content::EvalJs(
          wc, "'' + (window.uiTests && (typeof uiTests.dispatchOnTestSuite))"))
      << "DevTools front-end is broken.";
  LoadLegacyFilesInFrontend(window);
  DispatchOnTestSuiteSkipCheck(window, method, args...);
}

void RunTestFunction(DevToolsWindow* window, const char* test_name) {
  DispatchOnTestSuite(window, test_name);
}

void SwitchToPanel(DevToolsWindow* window, const char* panel) {
  DispatchOnTestSuite(window, "switchToPanel", panel);
}

// Version of SwitchToPanel that works with extension-created panels.
void SwitchToExtensionPanel(DevToolsWindow* window,
                            const Extension* devtools_extension,
                            const char* panel_name) {
  // The full name is the concatenation of the extension URL (stripped of its
  // trailing '/') and the |panel_name| that was passed to panels.create().
  std::string prefix(base::TrimString(devtools_extension->url().spec(), "/",
                                      base::TRIM_TRAILING));
  SwitchToPanel(window, (prefix + panel_name).c_str());
}

void DisallowDevToolsForForceInstalledExtenions(Browser* browser) {
  browser->profile()->GetPrefs()->SetInteger(
      prefs::kDevToolsAvailability,
      static_cast<int>(policy::DeveloperToolsPolicyHandler::Availability::
                           kDisallowedForForceInstalledExtensions));
}

void DisallowDevTools(Browser* browser) {
  browser->profile()->GetPrefs()->SetInteger(
      prefs::kDevToolsAvailability,
      static_cast<int>(
          policy::DeveloperToolsPolicyHandler::Availability::kDisallowed));
}

void AllowDevTools(Browser* browser) {
  browser->profile()->GetPrefs()->SetInteger(
      prefs::kDevToolsAvailability,
      static_cast<int>(
          policy::DeveloperToolsPolicyHandler::Availability::kAllowed));
}

scoped_refptr<DevToolsAgentHost> GetOrCreateDevToolsHostForWebContents(
    WebContents* wc) {
  return base::FeatureList::IsEnabled(::features::kDevToolsTabTarget)
             ? content::DevToolsAgentHost::GetOrCreateForTab(wc)
             : content::DevToolsAgentHost::GetOrCreateFor(wc);
}

}  // namespace

class DevToolsTest : public InProcessBrowserTest {
 public:
  DevToolsTest() : window_(nullptr) {}

  void SetUpOnMainThread() override {
    // A number of tests expect favicon requests to succeed - otherwise, they'll
    // generate console errors.
    embedded_test_server()->RegisterRequestHandler(
        base::BindRepeating(&DevToolsTest::HandleFaviconRequest));
    // LoadNetworkResourceForFrontend depends on "hello.html" from content's
    // test directory.
    embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
    ASSERT_TRUE(embedded_test_server()->Start());
    host_resolver()->AddRule("*", "127.0.0.1");
  }

 protected:
  static std::unique_ptr<net::test_server::HttpResponse> HandleFaviconRequest(
      const net::test_server::HttpRequest& request) {
    if (request.relative_url != "/favicon.ico") {
      return nullptr;
    }
    // The response doesn't have to be a valid favicon to avoid logging a
    // console error. Any 200 response will do.
    return std::make_unique<net::test_server::BasicHttpResponse>();
  }

  void RunTest(const std::string& test_name, const std::string& test_page) {
    OpenDevToolsWindow(test_page, false);
    RunTestFunction(window_, test_name.c_str());
    CloseDevToolsWindow();
  }

  template <typename... T>
  void RunTestMethod(const char* method, T... args) {
    DispatchOnTestSuiteSkipCheck(window_, method, args...);
  }

  template <typename... T>
  void DispatchAndWait(const char* method, T... args) {
    DispatchOnTestSuiteSkipCheck(window_, "waitForAsync", method, args...);
  }

  template <typename... T>
  void DispatchInPageAndWait(const char* method, T... args) {
    DispatchAndWait("invokePageFunctionAsync", method, args...);
  }

  void LoadTestPage(const std::string& test_page) {
    GURL url;
    if (base::StartsWith(test_page, "/")) {
      url = embedded_test_server()->GetURL(test_page);
    } else {
      url = GURL(test_page);
    }
    ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
  }

  void OpenDevToolsWindow(const std::string& test_page, bool is_docked) {
    LoadTestPage(test_page);

    window_ = DevToolsWindowTesting::OpenDevToolsWindowSync(GetInspectedTab(),
                                                            is_docked);
  }

  void OpenDevToolsWindowOnOffTheRecordTab(const std::string& test_page) {
    GURL url;
    if (base::StartsWith(test_page, "/")) {
      url = embedded_test_server()->GetURL(test_page);
    } else {
      url = GURL(test_page);
    }
    auto* otr_browser = OpenURLOffTheRecord(browser()->profile(), url);

    window_ = DevToolsWindowTesting::OpenDevToolsWindowSync(
        otr_browser->tab_strip_model()->GetWebContentsAt(0), false);
  }

  WebContents* GetInspectedTab() {
    return browser()->tab_strip_model()->GetWebContentsAt(0);
  }

  void CloseDevToolsWindow() {
    DevToolsWindowTesting::CloseDevToolsWindowSync(window_);
  }

  WebContents* main_web_contents() {
    return DevToolsWindowTesting::Get(window_)->main_web_contents();
  }

  WebContents* toolbox_web_contents() {
    return DevToolsWindowTesting::Get(window_)->toolbox_web_contents();
  }

  DevToolsWindow* window_;
};

class SitePerProcessDevToolsTest : public DevToolsTest {
 public:
  void SetUpCommandLine(base::CommandLine* command_line) override {
    DevToolsTest::SetUpCommandLine(command_line);
    content::IsolateAllSitesForTesting(command_line);
  }

  void SetUpOnMainThread() override {
    content::SetupCrossSiteRedirector(embedded_test_server());
    DevToolsTest::SetUpOnMainThread();
  }
};

// Used to block until a dev tools window gets beforeunload event.
class DevToolsWindowBeforeUnloadObserver : public content::WebContentsObserver {
 public:
  explicit DevToolsWindowBeforeUnloadObserver(DevToolsWindow*);

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

  void Wait();

 private:
  // Invoked when the beforeunload handler fires.
  void BeforeUnloadFired(bool proceed) override;

  bool m_fired;
  scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
};

DevToolsWindowBeforeUnloadObserver::DevToolsWindowBeforeUnloadObserver(
    DevToolsWindow* devtools_window)
    : WebContentsObserver(
          DevToolsWindowTesting::Get(devtools_window)->main_web_contents()),
      m_fired(false) {}

void DevToolsWindowBeforeUnloadObserver::Wait() {
  if (m_fired) {
    return;
  }
  message_loop_runner_ = base::MakeRefCounted<content::MessageLoopRunner>();
  message_loop_runner_->Run();
}

void DevToolsWindowBeforeUnloadObserver::BeforeUnloadFired(bool proceed) {
  m_fired = true;
  if (message_loop_runner_.get()) {
    message_loop_runner_->Quit();
  }
}

class DevToolsBeforeUnloadTest : public DevToolsTest {
 public:
  void CloseInspectedTab() {
    browser()->tab_strip_model()->CloseWebContentsAt(0,
                                                     TabCloseTypes::CLOSE_NONE);
  }

  void CloseDevToolsWindowAsync() {
    DevToolsWindowTesting::CloseDevToolsWindow(window_);
  }

  void CloseInspectedBrowser() { chrome::CloseWindow(browser()); }

 protected:
  void InjectBeforeUnloadListener(content::WebContents* web_contents) {
    ASSERT_TRUE(
        content::ExecJs(web_contents,
                        "window.addEventListener('beforeunload',"
                        "function(event) { event.returnValue = 'Foo'; });"));
    content::PrepContentsForBeforeUnloadTest(web_contents);
  }

  void RunBeforeUnloadTest(bool is_docked,
                           base::RepeatingCallback<void(void)> close_method,
                           bool wait_for_browser_close = true) {
    OpenDevToolsWindow(kDebuggerTestPage, is_docked);
    auto runner = base::MakeRefCounted<content::MessageLoopRunner>();
    DevToolsWindowTesting::Get(window_)->SetCloseCallback(
        runner->QuitClosure());
    InjectBeforeUnloadListener(main_web_contents());
    {
      DevToolsWindowBeforeUnloadObserver before_unload_observer(window_);
      close_method.Run();
      CancelModalDialog();
      before_unload_observer.Wait();
    }
    {
      close_method.Run();
      AcceptModalDialog();
      if (wait_for_browser_close) {
        ui_test_utils::WaitForBrowserToClose(browser());
      }
    }
    runner->Run();
  }

  DevToolsWindow* OpenDevToolWindowOnWebContents(content::WebContents* contents,
                                                 bool is_docked) {
    DevToolsWindow* window =
        DevToolsWindowTesting::OpenDevToolsWindowSync(contents, is_docked);
    return window;
  }

  void OpenDevToolsPopupWindow(DevToolsWindow* devtools_window) {
    content::WindowedNotificationObserver observer(
        content::NOTIFICATION_LOAD_STOP,
        content::NotificationService::AllSources());
    ASSERT_TRUE(content::ExecJs(
        DevToolsWindowTesting::Get(devtools_window)->main_web_contents(),
        "window.open(\"\", \"\", \"location=0\");"));
    observer.Wait();
  }

  void CloseDevToolsPopupWindow(DevToolsWindow* devtools_window) {
    DevToolsWindowTesting::CloseDevToolsWindowSync(devtools_window);
  }

  void AcceptModalDialog() {
    AppModalDialogView* view = GetDialog();
    view->AcceptAppModalDialog();
  }

  void CancelModalDialog() {
    AppModalDialogView* view = GetDialog();
    view->CancelAppModalDialog();
  }

  AppModalDialogView* GetDialog() {
    javascript_dialogs::AppModalDialogController* dialog =
        ui_test_utils::WaitForAppModalDialog();
    AppModalDialogView* view = dialog->view();
    EXPECT_TRUE(view);
    return view;
  }
};

void TimeoutCallback(const std::string& timeout_message) {
  ADD_FAILURE() << timeout_message;
  base::RunLoop::QuitCurrentWhenIdleDeprecated();
}

constexpr char kPublicKey[] =
    "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8c4fBSPZ6utYoZ8NiWF/"
    "DSaimBhihjwgOsskyleFGaurhi3TDClTVSGPxNkgCzrz0wACML7M4aNjpd05qupdbR2d294j"
    "kDuI7caxEGUucpP7GJRRHnm8Sx+"
    "y0ury28n8jbN0PnInKKWcxpIXXmNQyC19HBuO3QIeUq9Dqc+7YFQIDAQAB";

// Base class for DevTools tests that test devtools functionality for
// extensions and content scripts.
class DevToolsExtensionTest : public DevToolsTest {
 public:
  DevToolsExtensionTest()
      : test_extensions_dir_(
            base::PathService::CheckedGet(chrome::DIR_TEST_DATA)
                .AppendASCII("devtools")
                .AppendASCII("extensions")) {}

 protected:
  // Load an extension from test\data\devtools\extensions\<extension_name>
  void LoadExtension(const char* extension_name) {
    base::FilePath path = test_extensions_dir_.AppendASCII(extension_name);
    ASSERT_TRUE(LoadExtensionFromPath(path)) << "Failed to load extension.";
  }

  const Extension* LoadExtensionFromPath(const base::FilePath& path,
                                         bool allow_file_access = false) {
    extensions::ExtensionService* service =
        extensions::ExtensionSystem::Get(browser()->profile())
            ->extension_service();
    extensions::ExtensionRegistry* registry =
        extensions::ExtensionRegistry::Get(browser()->profile());
    extensions::TestExtensionRegistryObserver observer(registry);
    auto installer = extensions::UnpackedInstaller::Create(service);
    installer->set_allow_file_access(allow_file_access);
    installer->Load(path);
    observer.WaitForExtensionLoaded();

    // Wait for any additional extension views to load.
    extensions::ChromeExtensionTestNotificationObserver(browser())
        .WaitForExtensionViewsToLoad();

    return GetExtensionByPath(registry->enabled_extensions(), path);
  }

  base::Value::Dict BuildExtensionManifest(
      const std::string& name,
      const std::string& devtools_page = "",
      const std::string& key = "") {
    auto manifest = base::Value::Dict()
                        .Set("name", name)
                        .Set("version", "1")
                        .Set("manifest_version", 2)
                        // simple_test_page.html is currently the only page
                        // referenced outside of its own extension in the tests
                        .Set("web_accessible_resources",
                             base::Value::List()
                                 .Append("simple_test_page.html")
                                 .Append("source.map"));

    // If |devtools_page| isn't empty, make it a devtools extension in the
    // manifest.
    if (!devtools_page.empty()) {
      manifest.Set("devtools_page", devtools_page);
    }
    if (!key.empty()) {
      manifest.Set("key", key);
    }
    return manifest;
  }

  // Builds an extension populated with a bunch of test
  // pages. |name| is the extension name to use in the manifest.
  // |devtools_page|, if non-empty, indicates which test page should be be
  // listed as a devtools_page in the manifest.  If |devtools_page| is empty, a
  // non-devtools extension is created instead. |panel_iframe_src| controls the
  // src= attribute of the <iframe> element in the 'panel.html' test page.
  extensions::TestExtensionDir& BuildExtensionForTest(
      const std::string& name,
      const std::string& devtools_page,
      const std::string& panel_iframe_src) {
    test_extension_dirs_.emplace_back();
    extensions::TestExtensionDir& dir = test_extension_dirs_.back();

    dir.WriteManifest(BuildExtensionManifest(name, devtools_page));

    GURL http_frame_url =
        embedded_test_server()->GetURL("a.com", "/popup_iframe.html");

    // If this is a devtools extension, |devtools_page| will indicate which of
    // these devtools_pages will end up being used.  Different tests use
    // different devtools_pages.
    dir.WriteFile(FILE_PATH_LITERAL("web_devtools_page.html"),
                  "<html><body><iframe src='" + http_frame_url.spec() +
                      "'></iframe></body></html>");

    dir.WriteFile(FILE_PATH_LITERAL("simple_devtools_page.html"),
                  "<html><body></body></html>");

    dir.WriteFile(
        FILE_PATH_LITERAL("panel_devtools_page.html"),
        "<html><head><script "
        "src='panel_devtools_page.js'></script></head><body></body></html>");

    dir.WriteFile(FILE_PATH_LITERAL("panel_devtools_page.js"),
                  "chrome.devtools.panels.create('iframe_panel',\n"
                  "    null,\n"
                  "    'panel.html',\n"
                  "    function(panel) {\n"
                  "      chrome.devtools.inspectedWindow.eval(\n"
                  "        'console.log(\"PASS\")');\n"
                  "    }\n"
                  ");\n");

    dir.WriteFile(FILE_PATH_LITERAL("source.map"),
                  R"({"version":3,"sources":["foo.js"],"mappings":"AAyCAA"})");

    dir.WriteFile(FILE_PATH_LITERAL("sidebarpane_devtools_page.html"),
                  "<html><head><script src='sidebarpane_devtools_page.js'>"
                  "</script></head><body></body></html>");

    dir.WriteFile(
        FILE_PATH_LITERAL("sidebarpane_devtools_page.js"),
        "chrome.devtools.panels.elements.createSidebarPane('iframe_pane',\n"
        "    function(sidebar) {\n"
        "      chrome.devtools.inspectedWindow.eval(\n"
        "        'console.log(\"PASS\")');\n"
        "      sidebar.setPage('panel.html');\n"
        "    }\n"
        ");\n");

    dir.WriteFile(FILE_PATH_LITERAL("panel.html"),
                  "<html><body><iframe src='" + panel_iframe_src +
                      "'></iframe></body></html>");

    dir.WriteFile(FILE_PATH_LITERAL("simple_test_page.html"),
                  "<html><body>This is a test</body></html>");

    GURL web_url = embedded_test_server()->GetURL("a.com", "/title3.html");

    dir.WriteFile(FILE_PATH_LITERAL("multi_frame_page.html"),
                  "<html><body><iframe src='about:blank'>"
                  "</iframe><iframe src='data:text/html,foo'>"
                  "</iframe><iframe src='" +
                      web_url.spec() + "'></iframe></body></html>");
    return dir;
  }

  // Loads a dynamically generated extension populated with a bunch of test
  // pages.
  const Extension* LoadExtensionForTest(const std::string& name,
                                        const std::string& devtools_page,
                                        const std::string& panel_iframe_src) {
    extensions::TestExtensionDir& dir =
        BuildExtensionForTest(name, devtools_page, panel_iframe_src);
    return LoadExtensionFromPath(dir.UnpackedPath());
  }

  std::string BuildComponentExtension() {
    extensions::ExtensionService* extension_service =
        extensions::ExtensionSystem::Get(browser()->profile())
            ->extension_service();
    extensions::ComponentLoader* component_loader =
        extension_service->component_loader();
    extensions::ExtensionRegistry* extension_registry =
        extensions::ExtensionRegistry::Get(browser()->profile());

    extensions::TestExtensionDir& extension_dir =
        BuildExtensionForTest("Component extension", "" /* devtools_page */,
                              "" /* panel_iframe_src */);
    auto manifest = BuildExtensionManifest("Component extension",
                                           "" /* devtools_page */, kPublicKey);
    component_loader->set_ignore_allowlist_for_testing(true);
    std::string extension_id = component_loader->Add(
        std::move(manifest), extension_dir.UnpackedPath());
    EXPECT_TRUE(extension_registry->enabled_extensions().GetByID(extension_id));
    return extension_id;
  }

 private:
  const Extension* GetExtensionByPath(
      const extensions::ExtensionSet& extensions,
      const base::FilePath& path) {
    base::ScopedAllowBlockingForTesting allow_blocking;
    base::FilePath extension_path = base::MakeAbsoluteFilePath(path);
    EXPECT_TRUE(!extension_path.empty());
    for (const scoped_refptr<const Extension>& extension : extensions) {
      if (extension->path() == extension_path) {
        return extension.get();
      }
    }
    return nullptr;
  }

  // Use std::deque to avoid dangling references to existing elements.
  std::deque<extensions::TestExtensionDir> test_extension_dirs_;
  const base::FilePath test_extensions_dir_;
};

class DevToolsExperimentalExtensionTest : public DevToolsExtensionTest {
 public:
  void SetUpCommandLine(base::CommandLine* command_line) override {
    command_line->AppendSwitch(
        extensions::switches::kEnableExperimentalExtensionApis);
  }
};

class DevToolsServiceWorkerExtensionTest : public InProcessBrowserTest {
 protected:
  void SetUpOnMainThread() override {
    InProcessBrowserTest::SetUpOnMainThread();
    Profile* profile = browser()->profile();
    extension_service_ =
        extensions::ExtensionSystem::Get(profile)->extension_service();
    extension_registry_ = extensions::ExtensionRegistry::Get(profile);
  }

  const extensions::Extension* LoadExtension(base::FilePath extension_path) {
    extensions::TestExtensionRegistryObserver observer(extension_registry_);
    ExtensionTestMessageListener activated_listener("WORKER_ACTIVATED");
    extensions::UnpackedInstaller::Create(extension_service_)
        ->Load(extension_path);
    observer.WaitForExtensionLoaded();
    const extensions::Extension* extension = nullptr;
    for (const auto& enabled_extension :
         extension_registry_->enabled_extensions()) {
      if (enabled_extension->path() == extension_path) {
        extension = enabled_extension.get();
        break;
      }
    }
    CHECK(extension) << "Failed to find loaded extension " << extension_path;
    EXPECT_TRUE(activated_listener.WaitUntilSatisfied());
    return extension;
  }

  scoped_refptr<DevToolsAgentHost> FindExtensionHost(const std::string& id) {
    for (auto& host : DevToolsAgentHost::GetOrCreateAll()) {
      if (host->GetType() == DevToolsAgentHost::kTypeServiceWorker &&
          host->GetURL().host() == id) {
        return host;
      }
    }
    return nullptr;
  }

  void OpenDevToolsWindow(scoped_refptr<DevToolsAgentHost> host) {
    Profile* profile = browser()->profile();
    window_ = DevToolsWindowTesting::OpenDevToolsWindowSync(profile, host);
  }

  void CloseDevToolsWindow() {
    DevToolsWindowTesting::CloseDevToolsWindowSync(window_);
  }

  DevToolsWindow* window_ = nullptr;
  extensions::ExtensionService* extension_service_ = nullptr;
  extensions::ExtensionRegistry* extension_registry_ = nullptr;
};

IN_PROC_BROWSER_TEST_F(DevToolsServiceWorkerExtensionTest, AttachOnReload) {
  base::FilePath extension_path =
      base::PathService::CheckedGet(chrome::DIR_TEST_DATA)
          .AppendASCII("devtools")
          .AppendASCII("extensions")
          .AppendASCII("service_worker");
  std::string extension_id;
  {
    const extensions::Extension* extension = LoadExtension(extension_path);
    extension_id = extension->id();
  }
  scoped_refptr<DevToolsAgentHost> host = FindExtensionHost(extension_id);
  ASSERT_TRUE(host);
  OpenDevToolsWindow(host);
  extension_service_->ReloadExtension(extension_id);
  RunTestFunction(window_, "waitForTestResultsInConsole");
  CloseDevToolsWindow();
}

class WorkerDevToolsTest : public InProcessBrowserTest {
 public:
  WorkerDevToolsTest() : window_(nullptr) {}

  void SetUpOnMainThread() override {
    ASSERT_TRUE(embedded_test_server()->Start());
  }

 protected:
  class WorkerCreationObserver : public DevToolsAgentHostObserver {
   public:
    WorkerCreationObserver(const std::string& path,
                           scoped_refptr<DevToolsAgentHost>* out_host,
                           base::OnceClosure quit)
        : path_(path), out_host_(out_host), quit_(std::move(quit)) {
      DevToolsAgentHost::AddObserver(this);
    }

   private:
    ~WorkerCreationObserver() override {
      DevToolsAgentHost::RemoveObserver(this);
    }

    void DevToolsAgentHostCreated(DevToolsAgentHost* host) override {
      if (host->GetType() == DevToolsAgentHost::kTypeSharedWorker &&
          host->GetURL().path().rfind(path_) != std::string::npos) {
        *out_host_ = host;
        content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE,
                                                     std::move(quit_));
        delete this;
      }
    }

    std::string path_;
    scoped_refptr<DevToolsAgentHost>* out_host_;
    base::OnceClosure quit_;
  };

  static scoped_refptr<DevToolsAgentHost> WaitForFirstSharedWorker(
      const char* path) {
    for (auto& host : DevToolsAgentHost::GetOrCreateAll()) {
      if (host->GetType() == DevToolsAgentHost::kTypeSharedWorker &&
          host->GetURL().path().rfind(path) != std::string::npos) {
        return host;
      }
    }
    scoped_refptr<DevToolsAgentHost> host;
    base::RunLoop run_loop;
    new WorkerCreationObserver(path, &host, run_loop.QuitWhenIdleClosure());
    run_loop.Run();
    return host;
  }

  void OpenDevToolsWindow(scoped_refptr<DevToolsAgentHost> agent_host) {
    Profile* profile = browser()->profile();
    window_ =
        DevToolsWindowTesting::OpenDevToolsWindowSync(profile, agent_host);
  }

  void CloseDevToolsWindow() {
    DevToolsWindowTesting::CloseDevToolsWindowSync(window_);
  }

  DevToolsWindow* window_;
};

// Tests that BeforeUnload event gets called on docked devtools if
// we try to close them.
IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest, TestDockedDevToolsClose) {
  RunBeforeUnloadTest(
      true,
      base::BindRepeating(&DevToolsBeforeUnloadTest::CloseDevToolsWindowAsync,
                          base::Unretained(this)),
      false);
}

// Tests that BeforeUnload event gets called on docked devtools if
// we try to close the inspected page.
//
// TODO(https://crbug.com/1061052): Flaky on Windows.
#if BUILDFLAG(IS_WIN)
#define MAYBE_TestDockedDevToolsInspectedTabClose \
  DISABLED_TestDockedDevToolsInspectedTabClose
#else
#define MAYBE_TestDockedDevToolsInspectedTabClose \
  TestDockedDevToolsInspectedTabClose
#endif
IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,
                       MAYBE_TestDockedDevToolsInspectedTabClose) {
  RunBeforeUnloadTest(
      true, base::BindRepeating(&DevToolsBeforeUnloadTest::CloseInspectedTab,
                                base::Unretained(this)));
}

// Tests that BeforeUnload event gets called on docked devtools if
// we try to close the inspected browser.
IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,
                       TestDockedDevToolsInspectedBrowserClose) {
  RunBeforeUnloadTest(
      true,
      base::BindRepeating(&DevToolsBeforeUnloadTest::CloseInspectedBrowser,
                          base::Unretained(this)));
}

// Tests that BeforeUnload event gets called on undocked devtools if
// we try to close them.
IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest, TestUndockedDevToolsClose) {
  RunBeforeUnloadTest(
      false,
      base::BindRepeating(&DevToolsBeforeUnloadTest::CloseDevToolsWindowAsync,
                          base::Unretained(this)),
      false);
}

// Tests that BeforeUnload event gets called on undocked devtools if
// we try to close the inspected page.
IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,
                       TestUndockedDevToolsInspectedTabClose) {
  RunBeforeUnloadTest(
      false, base::BindRepeating(&DevToolsBeforeUnloadTest::CloseInspectedTab,
                                 base::Unretained(this)));
}

// Tests that BeforeUnload event gets called on undocked devtools if
// we try to close the inspected browser.
IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,
                       TestUndockedDevToolsInspectedBrowserClose) {
  RunBeforeUnloadTest(
      false,
      base::BindRepeating(&DevToolsBeforeUnloadTest::CloseInspectedBrowser,
                          base::Unretained(this)));
}

// Tests that BeforeUnload event gets called on undocked devtools if
// we try to exit application.
IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,
                       TestUndockedDevToolsApplicationClose) {
  RunBeforeUnloadTest(false, base::BindRepeating(&chrome::CloseAllBrowsers));
}

// Tests that inspected tab gets closed if devtools renderer
// becomes unresponsive during beforeunload event interception.
// @see http://crbug.com/322380
// Disabled because of http://crbug.com/410327
IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,
                       DISABLED_TestUndockedDevToolsUnresponsive) {
  LoadTestPage(kDebuggerTestPage);
  DevToolsWindow* devtools_window =
      OpenDevToolWindowOnWebContents(GetInspectedTab(), false);

  auto runner = base::MakeRefCounted<content::MessageLoopRunner>();
  DevToolsWindowTesting::Get(devtools_window)
      ->SetCloseCallback(runner->QuitClosure());

  ASSERT_TRUE(content::ExecJs(
      DevToolsWindowTesting::Get(devtools_window)->main_web_contents(),
      "window.addEventListener('beforeunload',"
      "function(event) { while (true); });"));
  CloseInspectedTab();
  runner->Run();
}

// Tests that closing worker inspector window does not cause browser crash
// @see http://crbug.com/323031
// TODO(https://crbug.com/1100888): Disabled due to flakiness.
IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,
                       DISABLED_TestWorkerWindowClosing) {
  LoadTestPage(kDebuggerTestPage);
  DevToolsWindow* devtools_window =
      OpenDevToolWindowOnWebContents(GetInspectedTab(), false);

  OpenDevToolsPopupWindow(devtools_window);
  CloseDevToolsPopupWindow(devtools_window);
}

// Tests that BeforeUnload event gets called on devtools that are opened
// on another devtools.
// TODO(https://crbug.com/1000654): Re-enable this test.
IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,
                       DISABLED_TestDevToolsOnDevTools) {
  LoadTestPage(kDebuggerTestPage);

  std::vector<DevToolsWindow*> windows;
  std::vector<std::unique_ptr<content::WebContentsDestroyedWatcher>>
      close_observers;
  content::WebContents* inspected_web_contents = GetInspectedTab();
  for (int i = 0; i < 3; ++i) {
    DevToolsWindow* devtools_window =
        OpenDevToolWindowOnWebContents(inspected_web_contents, i == 0);
    windows.push_back(devtools_window);
    close_observers.push_back(
        std::make_unique<content::WebContentsDestroyedWatcher>(
            DevToolsWindowTesting::Get(devtools_window)->main_web_contents()));
    inspected_web_contents =
        DevToolsWindowTesting::Get(devtools_window)->main_web_contents();
  }

  InjectBeforeUnloadListener(
      DevToolsWindowTesting::Get(windows[0])->main_web_contents());
  InjectBeforeUnloadListener(
      DevToolsWindowTesting::Get(windows[2])->main_web_contents());
  // Try to close second devtools.
  {
    chrome::CloseWindow(DevToolsWindowTesting::Get(windows[1])->browser());
    CancelModalDialog();
    base::RunLoop().RunUntilIdle();
    // The second devtools hasn't closed.
    EXPECT_EQ(windows[1],
              DevToolsWindow::GetInstanceForInspectedWebContents(
                  DevToolsWindowTesting::Get(windows[0])->main_web_contents()));
  }
  // Try to close browser window.
  {
    chrome::CloseWindow(browser());
    AcceptModalDialog();
    CancelModalDialog();
    base::RunLoop().RunUntilIdle();
    EXPECT_EQ(browser(), BrowserList::GetInstance()->get(0));
  }
  // Try to exit application.
  {
    chrome::CloseAllBrowsers();
    AcceptModalDialog();
    AcceptModalDialog();
    ui_test_utils::WaitForBrowserToClose(browser());
  }
  for (auto& close_observer : close_observers) {
    close_observer->Wait();
  }
}

// Tests scripts panel showing.
IN_PROC_BROWSER_TEST_F(DevToolsTest, TestShowScriptsTab) {
  RunTest("testShowScriptsTab", kDebuggerTestPage);
}

// Tests that chrome.devtools extension is correctly exposed.
IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest, TestDevToolsExtensionAPI) {
  LoadExtension("devtools_extension");
  RunTest("waitForTestResultsInConsole", kArbitraryPage);
}

// Tests that http Iframes within the visible devtools panel for the devtools
// extension are rendered in their own processes and not in the devtools process
// or the extension's process.  This is tested because this is one of the
// extension pages with devtools access
// (https://developer.chrome.com/extensions/devtools).  Also tests that frames
// with data URLs and about:blank URLs are rendered in the devtools process,
// unless a web OOPIF navigates itself to about:blank, in which case it does not
// end up back in the devtools process.  Also tests that when a web IFrame is
// navigated back to a devtools extension page, it gets put back in the devtools
// process.
// http://crbug.com/570483
IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest,
                       HttpIframeInDevToolsExtensionPanel) {
  // Install the dynamically-generated extension.
  const Extension* extension =
      LoadExtensionForTest("Devtools Extension", "panel_devtools_page.html",
                           "/multi_frame_page.html");
  ASSERT_TRUE(extension);

  OpenDevToolsWindow(kDebuggerTestPage, false);

  // Wait for the extension's panel to finish loading -- it'll output 'PASS'
  // when it's installed. waitForTestResultsInConsole waits until that 'PASS'.
  RunTestFunction(window_, "waitForTestResultsInConsole");

  // Now that we know the panel is loaded, switch to it.
  SwitchToExtensionPanel(window_, extension, "iframe_panel");
  EXPECT_TRUE(content::WaitForLoadStop(main_web_contents()));

  std::vector<RenderFrameHost*> rfhs =
      CollectAllRenderFrameHosts(main_web_contents());
  EXPECT_EQ(7U, rfhs.size());

  // This test creates a page with the following frame tree:
  // - DevTools
  //   - devtools_page from DevTools extension
  //   - Panel (DevTools extension)
  //     - iframe (DevTools extension)
  //       - about:blank
  //       - data:
  //       - web URL

  RenderFrameHost* main_devtools_rfh =
      main_web_contents()->GetPrimaryMainFrame();
  RenderFrameHost* devtools_extension_devtools_page_rfh =
      ChildFrameAt(main_devtools_rfh, 0);
  RenderFrameHost* devtools_extension_panel_rfh =
      ChildFrameAt(main_devtools_rfh, 1);
  RenderFrameHost* panel_frame_rfh =
      ChildFrameAt(devtools_extension_panel_rfh, 0);
  RenderFrameHost* about_blank_frame_rfh = ChildFrameAt(panel_frame_rfh, 0);
  RenderFrameHost* data_frame_rfh = ChildFrameAt(panel_frame_rfh, 1);
  RenderFrameHost* web_frame_rfh = ChildFrameAt(panel_frame_rfh, 2);

  GURL web_url = embedded_test_server()->GetURL("a.com", "/title3.html");
  GURL about_blank_url = GURL(url::kAboutBlankURL);
  GURL data_url = GURL("data:text/html,foo");

  EXPECT_TRUE(main_devtools_rfh->GetLastCommittedURL().SchemeIs(
      content::kChromeDevToolsScheme));
  EXPECT_EQ(extension->GetResourceURL("/panel_devtools_page.html"),
            devtools_extension_devtools_page_rfh->GetLastCommittedURL());
  EXPECT_EQ(extension->GetResourceURL("/panel.html"),
            devtools_extension_panel_rfh->GetLastCommittedURL());
  EXPECT_EQ(extension->GetResourceURL("/multi_frame_page.html"),
            panel_frame_rfh->GetLastCommittedURL());
  EXPECT_EQ(about_blank_url, about_blank_frame_rfh->GetLastCommittedURL());
  EXPECT_EQ(data_url, data_frame_rfh->GetLastCommittedURL());
  EXPECT_EQ(web_url, web_frame_rfh->GetLastCommittedURL());

  content::SiteInstance* devtools_instance =
      main_devtools_rfh->GetSiteInstance();
  content::SiteInstance* extensions_instance =
      devtools_extension_devtools_page_rfh->GetSiteInstance();

  EXPECT_TRUE(
      devtools_instance->GetSiteURL().SchemeIs(content::kChromeDevToolsScheme));
  EXPECT_TRUE(
      extensions_instance->GetSiteURL().SchemeIs(extensions::kExtensionScheme));

  EXPECT_NE(devtools_instance, extensions_instance);
  EXPECT_EQ(extensions_instance,
            devtools_extension_panel_rfh->GetSiteInstance());
  EXPECT_EQ(extensions_instance, panel_frame_rfh->GetSiteInstance());
  EXPECT_EQ(extensions_instance, about_blank_frame_rfh->GetSiteInstance());
  EXPECT_EQ(extensions_instance, data_frame_rfh->GetSiteInstance());

  EXPECT_EQ(web_url.host(),
            web_frame_rfh->GetSiteInstance()->GetSiteURL().host());
  EXPECT_NE(devtools_instance, web_frame_rfh->GetSiteInstance());
  EXPECT_NE(extensions_instance, web_frame_rfh->GetSiteInstance());

  // Check that if the web iframe navigates itself to about:blank, it stays in
  // the web SiteInstance.
  std::string about_blank_javascript = "location.href='about:blank';";

  content::TestNavigationManager web_about_blank_manager(main_web_contents(),
                                                         about_blank_url);

  ASSERT_TRUE(content::ExecJs(web_frame_rfh, about_blank_javascript));

  ASSERT_TRUE(web_about_blank_manager.WaitForNavigationFinished());
  // After navigation, the frame may change.
  web_frame_rfh = ChildFrameAt(panel_frame_rfh, 2);

  EXPECT_EQ(about_blank_url, web_frame_rfh->GetLastCommittedURL());
  EXPECT_EQ(web_url.host(),
            web_frame_rfh->GetSiteInstance()->GetSiteURL().host());
  EXPECT_NE(devtools_instance, web_frame_rfh->GetSiteInstance());
  EXPECT_NE(extensions_instance, web_frame_rfh->GetSiteInstance());

  // Check that if the web IFrame is navigated back to a devtools extension
  // page, it gets put back in the devtools process.
  GURL extension_simple_url =
      extension->GetResourceURL("/simple_test_page.html");
  std::string renavigation_javascript =
      "location.href='" + extension_simple_url.spec() + "';";

  content::TestNavigationManager renavigation_manager(main_web_contents(),
                                                      extension_simple_url);

  ASSERT_TRUE(content::ExecJs(web_frame_rfh, renavigation_javascript));

  ASSERT_TRUE(renavigation_manager.WaitForNavigationFinished());

  // The old RFH is no longer valid after the renavigation, so we must get the
  // new one.
  RenderFrameHost* extension_simple_frame_rfh =
      ChildFrameAt(panel_frame_rfh, 2);

  EXPECT_EQ(extension_simple_url,
            extension_simple_frame_rfh->GetLastCommittedURL());
  EXPECT_EQ(extensions_instance, extension_simple_frame_rfh->GetSiteInstance());
}

// Tests that http Iframes within the sidebar pane page for the devtools
// extension that is visible in the elements panel are rendered in their own
// processes and not in the devtools process or the extension's process.  This
// is tested because this is one of the extension pages with devtools access
// (https://developer.chrome.com/extensions/devtools).  http://crbug.com/570483
IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest,
                       HttpIframeInDevToolsExtensionSideBarPane) {
  GURL web_url = embedded_test_server()->GetURL("a.com", "/title3.html");

  // Install the dynamically-generated extension.
  const Extension* extension = LoadExtensionForTest(
      "Devtools Extension", "sidebarpane_devtools_page.html", web_url.spec());
  ASSERT_TRUE(extension);

  OpenDevToolsWindow(kDebuggerTestPage, false);

  // Wait for the extension's sidebarpane to finish loading -- it'll output
  // 'PASS' when it's installed. waitForTestResultsInConsole waits until that
  // 'PASS'.
  RunTestFunction(window_, "waitForTestResultsInConsole");

  // Now that we know the sidebarpane is loaded, switch to it.
  content::TestNavigationManager web_manager(main_web_contents(), web_url);
  SwitchToPanel(window_, "elements");
  // This is a bit of a hack to switch to the sidebar pane in the elements panel
  // that the Iframe has been added to.
  SwitchToPanel(window_, "iframe_pane");
  ASSERT_TRUE(web_manager.WaitForNavigationFinished());

  std::vector<RenderFrameHost*> rfhs =
      CollectAllRenderFrameHosts(main_web_contents());
  EXPECT_EQ(4U, rfhs.size());

  RenderFrameHost* main_devtools_rfh =
      main_web_contents()->GetPrimaryMainFrame();
  RenderFrameHost* devtools_extension_devtools_page_rfh =
      ChildFrameAt(main_devtools_rfh, 0);
  RenderFrameHost* devtools_sidebar_pane_extension_rfh =
      ChildFrameAt(main_devtools_rfh, 1);
  RenderFrameHost* http_iframe_rfh =
      ChildFrameAt(devtools_sidebar_pane_extension_rfh, 0);

  EXPECT_TRUE(main_devtools_rfh->GetLastCommittedURL().SchemeIs(
      content::kChromeDevToolsScheme));
  EXPECT_EQ(extension->GetResourceURL("/sidebarpane_devtools_page.html"),
            devtools_extension_devtools_page_rfh->GetLastCommittedURL());
  EXPECT_EQ(extension->GetResourceURL("/panel.html"),
            devtools_sidebar_pane_extension_rfh->GetLastCommittedURL());
  EXPECT_EQ(web_url, http_iframe_rfh->GetLastCommittedURL());

  content::SiteInstance* devtools_instance =
      main_devtools_rfh->GetSiteInstance();
  content::SiteInstance* extensions_instance =
      devtools_extension_devtools_page_rfh->GetSiteInstance();
  EXPECT_TRUE(
      devtools_instance->GetSiteURL().SchemeIs(content::kChromeDevToolsScheme));
  EXPECT_NE(devtools_instance, extensions_instance);
  EXPECT_EQ(extensions_instance,
            devtools_extension_devtools_page_rfh->GetSiteInstance());
  EXPECT_EQ(extensions_instance,
            devtools_sidebar_pane_extension_rfh->GetSiteInstance());
  EXPECT_EQ(web_url.host(),
            http_iframe_rfh->GetSiteInstance()->GetSiteURL().host());
  EXPECT_NE(devtools_instance, http_iframe_rfh->GetSiteInstance());
  EXPECT_NE(extensions_instance, http_iframe_rfh->GetSiteInstance());
}

// Tests that http Iframes within the devtools background page, which is
// different from the extension's background page, are rendered in their own
// processes and not in the devtools process or the extension's process.
IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest,
                       HttpIframeInDevToolsExtensionDevtools) {
  // Install the dynamically-generated extension.
  const Extension* extension =
      LoadExtensionForTest("Devtools Extension", "web_devtools_page.html",
                           "" /* panel_iframe_src */);
  ASSERT_TRUE(extension);

  // Wait for a 'DONE' message sent from popup_iframe.html, indicating that it
  // loaded successfully.
  std::unique_ptr<content::DOMMessageQueue> message_queue;
  std::string message;

  // OpenDevToolsWindow() internally creates and initializes a WebContents,
  // which we need to listen to messages from; to ensure that we don't miss
  // the message, listen for that WebContents being created and set up a
  // DOMMessageQueue for it.
  {
    auto subscription = content::RegisterWebContentsCreationCallback(
        // Note that we only care about the first WebContents; for all
        // subsequent WebContents, message_queue will already be non-null.
        base::BindLambdaForTesting([&](content::WebContents* contents) {
          if (!message_queue) {
            message_queue =
                std::make_unique<content::DOMMessageQueue>(contents);
          }
        }));
    OpenDevToolsWindow(kDebuggerTestPage, false);
  }

  ASSERT_TRUE(message_queue)
      << "OpenDevToolsWindow must create at least one WebContents";
  while (true) {
    ASSERT_TRUE(message_queue->WaitForMessage(&message));
    if (message == "\"DONE\"") {
      break;
    }
  }

  std::vector<RenderFrameHost*> rfhs =
      CollectAllRenderFrameHosts(main_web_contents());
  EXPECT_EQ(3U, rfhs.size());

  RenderFrameHost* main_devtools_rfh =
      main_web_contents()->GetPrimaryMainFrame();
  RenderFrameHost* devtools_extension_devtools_page_rfh =
      ChildFrameAt(main_devtools_rfh, 0);
  RenderFrameHost* http_iframe_rfh =
      ChildFrameAt(devtools_extension_devtools_page_rfh, 0);

  GURL web_url = embedded_test_server()->GetURL("a.com", "/popup_iframe.html");

  EXPECT_TRUE(main_devtools_rfh->GetLastCommittedURL().SchemeIs(
      content::kChromeDevToolsScheme));
  EXPECT_EQ(extension->GetResourceURL("/web_devtools_page.html"),
            devtools_extension_devtools_page_rfh->GetLastCommittedURL());
  EXPECT_EQ(web_url, http_iframe_rfh->GetLastCommittedURL());

  content::SiteInstance* devtools_instance =
      main_devtools_rfh->GetSiteInstance();
  content::SiteInstance* extensions_instance =
      devtools_extension_devtools_page_rfh->GetSiteInstance();

  EXPECT_TRUE(
      devtools_instance->GetSiteURL().SchemeIs(content::kChromeDevToolsScheme));
  EXPECT_NE(devtools_instance, extensions_instance);
  EXPECT_EQ(web_url.host(),
            http_iframe_rfh->GetSiteInstance()->GetSiteURL().host());
  EXPECT_NE(devtools_instance, http_iframe_rfh->GetSiteInstance());
  EXPECT_NE(extensions_instance, http_iframe_rfh->GetSiteInstance());
}

// Tests that iframes to a non-devtools extension embedded in a devtools
// extension will be isolated from devtools and the devtools extension.
// http://crbug.com/570483
// Disabled due to flakiness https://crbug.com/1062802
IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest,
                       DISABLED_NonDevToolsExtensionInDevToolsExtension) {
  // Install the dynamically-generated non-devtools extension.
  const Extension* non_devtools_extension =
      LoadExtensionForTest("Non-DevTools Extension", "" /* devtools_page */,
                           "" /* panel_iframe_src */);
  ASSERT_TRUE(non_devtools_extension);

  GURL non_dt_extension_test_url =
      non_devtools_extension->GetResourceURL("/simple_test_page.html");

  // Install the dynamically-generated devtools extension.
  const Extension* devtools_extension =
      LoadExtensionForTest("Devtools Extension", "panel_devtools_page.html",
                           non_dt_extension_test_url.spec());
  ASSERT_TRUE(devtools_extension);

  OpenDevToolsWindow(kDebuggerTestPage, false);

  // Wait for the extension's panel to finish loading -- it'll output 'PASS'
  // when it's installed. waitForTestResultsInConsole waits until that 'PASS'.
  RunTestFunction(window_, "waitForTestResultsInConsole");

  // Now that we know the panel is loaded, switch to it.
  content::TestNavigationManager non_devtools_manager(
      main_web_contents(), non_dt_extension_test_url);
  SwitchToExtensionPanel(window_, devtools_extension, "iframe_panel");
  ASSERT_TRUE(non_devtools_manager.WaitForNavigationFinished());

  std::vector<RenderFrameHost*> rfhs =
      CollectAllRenderFrameHosts(main_web_contents());
  EXPECT_EQ(4U, rfhs.size());

  RenderFrameHost* main_devtools_rfh =
      main_web_contents()->GetPrimaryMainFrame();
  RenderFrameHost* devtools_extension_devtools_page_rfh =
      ChildFrameAt(main_devtools_rfh, 0);
  RenderFrameHost* devtools_extension_panel_rfh =
      ChildFrameAt(main_devtools_rfh, 1);
  RenderFrameHost* non_devtools_extension_rfh =
      ChildFrameAt(devtools_extension_panel_rfh, 0);

  EXPECT_TRUE(main_devtools_rfh->GetLastCommittedURL().SchemeIs(
      content::kChromeDevToolsScheme));
  EXPECT_EQ(devtools_extension->GetResourceURL("/panel_devtools_page.html"),
            devtools_extension_devtools_page_rfh->GetLastCommittedURL());
  EXPECT_EQ(devtools_extension->GetResourceURL("/panel.html"),
            devtools_extension_panel_rfh->GetLastCommittedURL());
  EXPECT_EQ(non_dt_extension_test_url,
            non_devtools_extension_rfh->GetLastCommittedURL());

  // simple_test_page.html's frame should be in |non_devtools_extension|'s
  // process, not in devtools or |devtools_extension|'s process.
  content::SiteInstance* devtools_instance =
      main_devtools_rfh->GetSiteInstance();
  content::SiteInstance* extensions_instance =
      devtools_extension_devtools_page_rfh->GetSiteInstance();
  EXPECT_TRUE(
      devtools_instance->GetSiteURL().SchemeIs(content::kChromeDevToolsScheme));
  EXPECT_NE(devtools_instance, extensions_instance);
  EXPECT_EQ(extensions_instance,
            devtools_extension_panel_rfh->GetSiteInstance());
  EXPECT_EQ(non_dt_extension_test_url.DeprecatedGetOriginAsURL(),
            non_devtools_extension_rfh->GetSiteInstance()->GetSiteURL());
  EXPECT_NE(devtools_instance, non_devtools_extension_rfh->GetSiteInstance());
  EXPECT_NE(extensions_instance, non_devtools_extension_rfh->GetSiteInstance());
}

// Tests that if a devtools extension's devtools panel page has a subframe to a
// page for another devtools extension, the subframe is rendered in the devtools
// process as well.  http://crbug.com/570483
IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest,
                       DevToolsExtensionInDevToolsExtension) {
  // Install the dynamically-generated extension.
  const Extension* devtools_b_extension =
      LoadExtensionForTest("Devtools Extension B", "simple_devtools_page.html",
                           "" /* panel_iframe_src */);
  ASSERT_TRUE(devtools_b_extension);

  GURL extension_b_page_url =
      devtools_b_extension->GetResourceURL("/simple_test_page.html");

  // Install another dynamically-generated extension.  This extension's
  // panel.html's iframe will point to an extension b URL.
  const Extension* devtools_a_extension =
      LoadExtensionForTest("Devtools Extension A", "panel_devtools_page.html",
                           extension_b_page_url.spec());
  ASSERT_TRUE(devtools_a_extension);

  OpenDevToolsWindow(kDebuggerTestPage, false);

  // Wait for the extension's panel to finish loading -- it'll output 'PASS'
  // when it's installed. waitForTestResultsInConsole waits until that 'PASS'.
  RunTestFunction(window_, "waitForTestResultsInConsole");

  // Now that we know the panel is loaded, switch to it.
  content::TestNavigationManager extension_b_manager(main_web_contents(),
                                                     extension_b_page_url);
  SwitchToExtensionPanel(window_, devtools_a_extension, "iframe_panel");
  ASSERT_TRUE(extension_b_manager.WaitForNavigationFinished());

  std::vector<RenderFrameHost*> rfhs =
      CollectAllRenderFrameHosts(main_web_contents());
  EXPECT_EQ(5U, rfhs.size());

  RenderFrameHost* main_devtools_rfh =
      main_web_contents()->GetPrimaryMainFrame();

  RenderFrameHost* devtools_extension_a_devtools_rfh =
      content::FrameMatchingPredicate(
          main_web_contents()->GetPrimaryPage(),
          base::BindRepeating(&content::FrameHasSourceUrl,
                              devtools_a_extension->GetResourceURL(
                                  "/panel_devtools_page.html")));
  EXPECT_TRUE(devtools_extension_a_devtools_rfh);
  RenderFrameHost* devtools_extension_b_devtools_rfh =
      content::FrameMatchingPredicate(
          main_web_contents()->GetPrimaryPage(),
          base::BindRepeating(&content::FrameHasSourceUrl,
                              devtools_b_extension->GetResourceURL(
                                  "/simple_devtools_page.html")));
  EXPECT_TRUE(devtools_extension_b_devtools_rfh);

  RenderFrameHost* devtools_extension_a_panel_rfh =
      ChildFrameAt(main_devtools_rfh, 2);
  RenderFrameHost* devtools_extension_b_frame_rfh =
      ChildFrameAt(devtools_extension_a_panel_rfh, 0);

  EXPECT_TRUE(main_devtools_rfh->GetLastCommittedURL().SchemeIs(
      content::kChromeDevToolsScheme));
  EXPECT_EQ(devtools_a_extension->GetResourceURL("/panel_devtools_page.html"),
            devtools_extension_a_devtools_rfh->GetLastCommittedURL());
  EXPECT_EQ(devtools_b_extension->GetResourceURL("/simple_devtools_page.html"),
            devtools_extension_b_devtools_rfh->GetLastCommittedURL());
  EXPECT_EQ(devtools_a_extension->GetResourceURL("/panel.html"),
            devtools_extension_a_panel_rfh->GetLastCommittedURL());
  EXPECT_EQ(extension_b_page_url,
            devtools_extension_b_frame_rfh->GetLastCommittedURL());

  // Main extension frame should be loaded in the extensions process. Nested
  // iframes should be loaded consistently with any other extensions iframes
  // (in or out of process).
  content::SiteInstance* devtools_instance =
      main_devtools_rfh->GetSiteInstance();
  content::SiteInstance* extension_a_instance =
      devtools_extension_a_devtools_rfh->GetSiteInstance();
  content::SiteInstance* extension_b_instance =
      devtools_extension_b_devtools_rfh->GetSiteInstance();
  EXPECT_TRUE(
      devtools_instance->GetSiteURL().SchemeIs(content::kChromeDevToolsScheme));
  EXPECT_NE(devtools_instance, extension_a_instance);
  EXPECT_NE(devtools_instance, extension_b_instance);
  EXPECT_NE(extension_a_instance, extension_b_instance);
  EXPECT_EQ(extension_a_instance,
            devtools_extension_a_panel_rfh->GetSiteInstance());
  EXPECT_EQ(extension_b_instance,
            devtools_extension_b_frame_rfh->GetSiteInstance());
}

// Tests that a devtools extension can still have subframes to itself in a
// "devtools page" and that they will be rendered within the extension process
// as well, not in some other process.
IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest, DevToolsExtensionInItself) {
  // Install the dynamically-generated extension.
  const Extension* extension =
      LoadExtensionForTest("Devtools Extension", "panel_devtools_page.html",
                           "/simple_test_page.html");
  ASSERT_TRUE(extension);

  OpenDevToolsWindow(kDebuggerTestPage, false);

  // Wait for the extension's panel to finish loading -- it'll output 'PASS'
  // when it's installed. waitForTestResultsInConsole waits until that 'PASS'.
  RunTestFunction(window_, "waitForTestResultsInConsole");

  // Now that we know the panel is loaded, switch to it.
  GURL extension_test_url = extension->GetResourceURL("/simple_test_page.html");
  content::TestNavigationManager test_page_manager(main_web_contents(),
                                                   extension_test_url);
  SwitchToExtensionPanel(window_, extension, "iframe_panel");
  ASSERT_TRUE(test_page_manager.WaitForNavigationFinished());

  std::vector<RenderFrameHost*> rfhs =
      CollectAllRenderFrameHosts(main_web_contents());
  EXPECT_EQ(4U, rfhs.size());

  RenderFrameHost* main_devtools_rfh =
      main_web_contents()->GetPrimaryMainFrame();
  RenderFrameHost* devtools_extension_devtools_page_rfh =
      ChildFrameAt(main_devtools_rfh, 0);
  RenderFrameHost* devtools_extension_panel_rfh =
      ChildFrameAt(main_devtools_rfh, 1);
  RenderFrameHost* devtools_extension_panel_frame_rfh =
      ChildFrameAt(devtools_extension_panel_rfh, 0);

  // Extension frames should be in the extensions process, including
  // simple_test_page.html
  EXPECT_TRUE(main_devtools_rfh->GetLastCommittedURL().SchemeIs(
      content::kChromeDevToolsScheme));
  EXPECT_EQ(extension->GetResourceURL("/panel_devtools_page.html"),
            devtools_extension_devtools_page_rfh->GetLastCommittedURL());
  EXPECT_EQ(extension->GetResourceURL("/panel.html"),
            devtools_extension_panel_rfh->GetLastCommittedURL());
  EXPECT_EQ(extension_test_url,
            devtools_extension_panel_frame_rfh->GetLastCommittedURL());

  content::SiteInstance* devtools_instance =
      main_devtools_rfh->GetSiteInstance();
  content::SiteInstance* extensions_instance =
      devtools_extension_devtools_page_rfh->GetSiteInstance();
  EXPECT_TRUE(
      devtools_instance->GetSiteURL().SchemeIs(content::kChromeDevToolsScheme));
  EXPECT_EQ(extensions_instance,
            devtools_extension_panel_rfh->GetSiteInstance());
  EXPECT_EQ(extensions_instance,
            devtools_extension_panel_frame_rfh->GetSiteInstance());
}

// Tests that a devtools (not a devtools extension) Iframe can be injected into
// devtools.  http://crbug.com/570483
// crbug.com/1124981: flaky on win
#if BUILDFLAG(IS_WIN)
#define MAYBE_DevtoolsInDevTools DISABLED_DevtoolsInDevTools
#else
#define MAYBE_DevtoolsInDevTools DevtoolsInDevTools
#endif
IN_PROC_BROWSER_TEST_F(DevToolsTest, MAYBE_DevtoolsInDevTools) {
  GURL devtools_url = GURL(chrome::kChromeUIDevToolsURL);

  OpenDevToolsWindow(kDebuggerTestPage, false);

  std::string javascript =
      "var devtoolsFrame = document.createElement('iframe');"
      "document.body.appendChild(devtoolsFrame);"
      "devtoolsFrame.src = '" +
      devtools_url.spec() + "';";

  RenderFrameHost* main_devtools_rfh =
      main_web_contents()->GetPrimaryMainFrame();

  content::TestNavigationManager manager(main_web_contents(), devtools_url);
  ASSERT_TRUE(content::ExecJs(main_devtools_rfh, javascript));
  ASSERT_TRUE(manager.WaitForNavigationFinished());

  std::vector<RenderFrameHost*> rfhs =
      CollectAllRenderFrameHosts(main_web_contents());
  EXPECT_EQ(2U, rfhs.size());
  RenderFrameHost* devtools_iframe_rfh = ChildFrameAt(main_devtools_rfh, 0);
  EXPECT_TRUE(main_devtools_rfh->GetLastCommittedURL().SchemeIs(
      content::kChromeDevToolsScheme));
  EXPECT_EQ(devtools_url, devtools_iframe_rfh->GetLastCommittedURL());
  content::SiteInstance* devtools_instance =
      main_devtools_rfh->GetSiteInstance();
  EXPECT_TRUE(
      devtools_instance->GetSiteURL().SchemeIs(content::kChromeDevToolsScheme));
  EXPECT_EQ(devtools_instance, devtools_iframe_rfh->GetSiteInstance());

  std::string message =
      content::EvalJs(devtools_iframe_rfh, "self.origin").ExtractString();
  EXPECT_EQ(devtools_url.DeprecatedGetOriginAsURL().spec(), message + "/");
}

// Some web features, when used from an extension, are subject to browser-side
// security policy enforcement. Make sure they work properly from inside a
// devtools extension.
// ToDo(993982): The test is flaky (timeout, crash, and fail) on several builds:
// Debug, Windows, Mac, MSan, and ASan.
IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest,
                       DISABLED_DevToolsExtensionSecurityPolicyGrants) {
  auto dir = std::make_unique<extensions::TestExtensionDir>();

  dir->WriteManifest(base::Value::Dict()
                         .Set("name", "Devtools Panel")
                         .Set("version", "1")
                         // Allow the script we stuff into the 'blob:' URL:
                         .Set("content_security_policy",
                              "script-src 'self' "
                              "'sha256-uv9gxBEOFchPzak3TK6O39RdKxJeZvfha9zOHGam"
                              "TB4='; "
                              "object-src 'none'")
                         .Set("manifest_version", 2)
                         .Set("devtools_page", "devtools.html"));

  dir->WriteFile(
      FILE_PATH_LITERAL("devtools.html"),
      "<html><head><script src='devtools.js'></script></head></html>");

  dir->WriteFile(
      FILE_PATH_LITERAL("devtools.js"),
      "chrome.devtools.panels.create('the_panel_name',\n"
      "    null,\n"
      "    'panel.html',\n"
      "    function(panel) {\n"
      "      chrome.devtools.inspectedWindow.eval('console.log(\"PASS\")');\n"
      "    }\n"
      ");\n");

  dir->WriteFile(FILE_PATH_LITERAL("panel.html"),
                 "<html><body>A panel."
                 "<script src='blob_xhr.js'></script>"
                 "<script src='blob_iframe.js'></script>"
                 "</body></html>");
  // Creating blobs from chrome-extension:// origins is only permitted if the
  // process has been granted permission to commit 'chrome-extension' schemes.
  dir->WriteFile(
      FILE_PATH_LITERAL("blob_xhr.js"),
      "var blob_url = URL.createObjectURL(new Blob(['xhr blob contents']));\n"
      "var xhr = new XMLHttpRequest();\n"
      "xhr.open('GET', blob_url, true);\n"
      "xhr.onload = function (e) {\n"
      "    domAutomationController.send(xhr.response);\n"
      "};\n"
      "xhr.send(null);\n");
  dir->WriteFile(
      FILE_PATH_LITERAL("blob_iframe.js"),
      "var payload = `"
      "<html><body>iframe blob contents"
      "<script>"
      "    domAutomationController.send(document.body.innerText);\n"
      "</script></body></html>"
      "`;"
      "document.body.appendChild(document.createElement('iframe')).src ="
      "    URL.createObjectURL(new Blob([payload], {type: 'text/html'}));");
  // Install the extension.
  const Extension* extension = LoadExtensionFromPath(dir->UnpackedPath());
  ASSERT_TRUE(extension);

  // Open a devtools window.
  OpenDevToolsWindow(kDebuggerTestPage, false);

  // Wait for the panel extension to finish loading -- it'll output 'PASS'
  // when it's installed. waitForTestResultsInConsole waits until that 'PASS'.
  RunTestFunction(window_, "waitForTestResultsInConsole");

  // Now that we know the panel is loaded, switch to it. We'll wait until we
  // see a 'DONE' message sent from popup_iframe.html, indicating that it
  // loaded successfully.
  content::DOMMessageQueue message_queue(main_web_contents());
  SwitchToExtensionPanel(window_, extension, "the_panel_name");
  std::string message;
  while (true) {
    ASSERT_TRUE(message_queue.WaitForMessage(&message));
    if (message == "\"xhr blob contents\"") {
      break;
    }
  }
  while (true) {
    ASSERT_TRUE(message_queue.WaitForMessage(&message));
    if (message == "\"iframe blob contents\"") {
      break;
    }
  }
}

// Disabled on Windows due to flakiness. http://crbug.com/183649
#if BUILDFLAG(IS_WIN)
#define MAYBE_TestDevToolsExtensionMessaging \
  DISABLED_TestDevToolsExtensionMessaging
#else
#define MAYBE_TestDevToolsExtensionMessaging TestDevToolsExtensionMessaging
#endif

// Tests that chrome.devtools extension can communicate with background page
// using extension messaging.
IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest,
                       MAYBE_TestDevToolsExtensionMessaging) {
  LoadExtension("devtools_messaging");
  RunTest("waitForTestResultsInConsole", kArbitraryPage);
}

// Tests that chrome.experimental.devtools extension is correctly exposed
// when the extension has experimental permission.
IN_PROC_BROWSER_TEST_F(DevToolsExperimentalExtensionTest,
                       TestDevToolsExperimentalExtensionAPI) {
  LoadExtension("devtools_experimental");
  RunTest("waitForTestResultsInConsole", kArbitraryPage);
}

// Tests that a content script is in the scripts list.
IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest, TestContentScriptIsPresent) {
  LoadExtension("simple_content_script");
  RunTest("testContentScriptIsPresent", kPageWithContentScript);
}

// Tests that console selector shows correct context names.
IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest, TestConsoleContextNames) {
  LoadExtension("simple_content_script");
  RunTest("testConsoleContextNames", kPageWithContentScript);
}

IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest, CantInspectNewTabPage) {
  LoadExtension("can_inspect_url");
  RunTest("waitForTestResultsAsMessage",
          base::StrCat({kArbitraryPage, "#chrome://newtab/"}));
}

IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest, CantInspectChromeScheme) {
  LoadExtension("can_inspect_url");
  RunTest("waitForTestResultsAsMessage",
          base::StrCat({kArbitraryPage, "#chrome://version/"}));
}

IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest, CantInspectDevtoolsScheme) {
  LoadExtension("can_inspect_url");
  RunTest(
      "waitForTestResultsAsMessage",
      base::StrCat({kArbitraryPage,
                    "#devtools://devtools/bundled/devtools_compatibility.js"}));
}

IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest,
                       CantInspectViewSourceDevtoolsScheme) {
  LoadExtension("can_inspect_url");
  RunTest("waitForTestResultsAsMessage",
          base::StrCat({kArbitraryPage,
                        "#view-source:devtools://devtools/bundled/"
                        "devtools_compatibility.js"}));
}

IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest, CantInspectComponentExtension) {
  std::string extension_id = BuildComponentExtension();
  LoadExtension("can_inspect_url");
  RunTest("waitForTestResultsAsMessage",
          base::StrCat({kArbitraryPage, "#chrome-extension://", extension_id,
                        "/simple_test_page.html"}));
}

IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest,
                       CantInspectViewSourceComponentExtension) {
  std::string extension_id = BuildComponentExtension();
  LoadExtension("can_inspect_url");
  RunTest("waitForTestResultsAsMessage",
          base::StrCat({kArbitraryPage, "#view-source:chrome-extension://",
                        extension_id, "/simple_test_page.html"}));
}

class DevToolsExtensionSidePanelTest
    : public DevToolsExtensionTest,
      public ::testing::WithParamInterface<bool> {
 public:
  DevToolsExtensionSidePanelTest() {
    if (GetParam()) {
      feature_list_.InitWithFeatures(
          /*enabled_features=*/{extensions_features::
                                    kExtensionSidePanelIntegration,
                                ::features::kDevToolsTabTarget},
          /*disabled_features=*/{});
    } else {
      feature_list_.InitWithFeatures(
          /*enabled_features=*/{extensions_features::
                                    kExtensionSidePanelIntegration},
          /*disabled_features=*/{::features::kDevToolsTabTarget});
    }
  }

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

// Test that an extension's side panel view is inspectable whether or not the
// `kDevToolsTabTarget` flag is enabled.
IN_PROC_BROWSER_TEST_P(DevToolsExtensionSidePanelTest,
                       CanInspectExtensionSidePanelView) {
  base::FilePath side_panel_extension_dir =
      base::PathService::CheckedGet(chrome::DIR_TEST_DATA)
          .AppendASCII("extensions/api_test/side_panel");

  // Load an extension and wait for its side panel view to be shown.
  scoped_refptr<const extensions::Extension> extension = LoadExtensionFromPath(
      side_panel_extension_dir.AppendASCII("simple_default"));
  ASSERT_TRUE(extension);

  ExtensionTestMessageListener default_path_listener("default_path");
  extensions::OpenExtensionSidePanel(*browser(), extension->id());
  ASSERT_TRUE(default_path_listener.WaitUntilSatisfied());

  content::WebContents* side_panel_contents =
      extensions::GetExtensionSidePanelWebContents(*browser(), extension->id());
  ASSERT_TRUE(side_panel_contents);
  EXPECT_TRUE(content::WaitForLoadStop(side_panel_contents));

  std::vector<RenderFrameHost*> frames =
      CollectAllRenderFrameHosts(side_panel_contents);
  ASSERT_EQ(1u, frames.size());
  RenderFrameHost* side_panel_host = frames[0];

  // Inspect the extension's side panel view and check that the top level html
  // tag is inspected.
  DevToolsWindowCreationObserver observer;
  DevToolsWindow::InspectElement(side_panel_host, 0, 0);
  observer.WaitForLoad();
  DevToolsWindow* window = observer.devtools_window();

  DispatchOnTestSuite(window, "testInspectedElementIs", "HTML");
  DevToolsWindowTesting::CloseDevToolsWindowSync(window);
}

INSTANTIATE_TEST_SUITE_P(All,
                         DevToolsExtensionSidePanelTest,
                         ::testing::Bool(),
                         [](const testing::TestParamInfo<
                             DevToolsExtensionSidePanelTest::ParamType>& info) {
                           return info.param ? "DevToolsTabTargetEnabled"
                                             : "DevToolsTabTargetDisabled";
                         });

IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest, CanInspectExtensionOffscreenDoc) {
  static constexpr char kManifest[] =
      R"({
           "name": "Offscreen Document Test",
           "manifest_version": 3,
           "version": "0.1"
         })";
  extensions::TestExtensionDir test_dir;
  test_dir.WriteManifest(kManifest);
  test_dir.WriteFile(FILE_PATH_LITERAL("offscreen.html"),
                     "<html>offscreen</html>");

  const extensions::Extension* extension =
      LoadExtensionFromPath(test_dir.UnpackedPath());

  // Create an offscreen document and wait for it to load.
  GURL offscreen_url = extension->GetResourceURL("offscreen.html");
  std::unique_ptr<extensions::OffscreenDocumentHost> offscreen_document =
      std::make_unique<extensions::OffscreenDocumentHost>(
          *extension,
          extensions::ProcessManager::Get(browser()->profile())
              ->GetSiteInstanceForURL(offscreen_url)
              .get(),
          offscreen_url);
  {
    extensions::ExtensionHostTestHelper offscreen_waiter(browser()->profile(),
                                                         extension->id());
    offscreen_waiter.RestrictToType(
        extensions::mojom::ViewType::kOffscreenDocument);
    offscreen_document->CreateRendererSoon();
    offscreen_waiter.WaitForHostCompletedFirstLoad();
  }

  // Get the list of inspectable views for the extension.
  auto get_info_function = base::MakeRefCounted<
      extensions::api::DeveloperPrivateGetExtensionInfoFunction>();
  absl::optional<base::Value> result =
      extensions::api_test_utils::RunFunctionAndReturnSingleResult(
          get_info_function.get(),
          content::JsReplace(R"([$1])", extension->id()), browser()->profile());
  ASSERT_TRUE(result);
  std::unique_ptr<extensions::api::developer_private::ExtensionInfo> info =
      extensions::api::developer_private::ExtensionInfo::FromValueDeprecated(
          *result);
  ASSERT_TRUE(info);

  // The only inspectable view should be the offscreen document. Validate the
  // metadata.
  ASSERT_EQ(1u, info->views.size());
  const extensions::api::developer_private::ExtensionView& view =
      info->views[0];
  EXPECT_EQ(extensions::api::developer_private::VIEW_TYPE_OFFSCREEN_DOCUMENT,
            view.type);
  content::WebContents* offscreen_contents =
      offscreen_document->host_contents();
  EXPECT_EQ(offscreen_url.spec(), view.url);
  EXPECT_EQ(offscreen_document->render_process_host()->GetID(),
            view.render_process_id);
  EXPECT_EQ(offscreen_contents->GetPrimaryMainFrame()->GetRoutingID(),
            view.render_view_id);
  EXPECT_FALSE(view.incognito);
  EXPECT_FALSE(view.is_iframe);

  // The document shouldn't currently be under inspection.
  EXPECT_FALSE(
      DevToolsWindow::GetInstanceForInspectedWebContents(offscreen_contents));
  DevToolsWindowCreationObserver observer;

  // Call the API function to inspect the offscreen document.
  auto dev_tools_function = base::MakeRefCounted<
      extensions::api::DeveloperPrivateOpenDevToolsFunction>();
  extensions::api_test_utils::RunFunction(
      dev_tools_function.get(),
      content::JsReplace(
          R"([{"renderViewId": $1,
               "renderProcessId": $2,
               "extensionId": $3
            }])",
          view.render_view_id, view.render_process_id, extension->id()),
      browser()->profile());

  // Validate that the devtools window is now shown.
  observer.WaitForLoad();
  content::RenderFrameHost* rfh = content::RenderFrameHost::FromID(
      view.render_process_id, view.render_view_id);
  ASSERT_TRUE(rfh);
  DevToolsWindow::InspectElement(rfh, 0, 0);
  DispatchOnTestSuite(observer.devtools_window(), "testInspectedElementIs",
                      "HTML");
}

class DevToolsExtensionFileAccessTest : public DevToolsExtensionTest {
 protected:
  void Run(bool allow_file_access, const std::string& url_scheme) {
    extensions::TestExtensionDir dir;

    dir.WriteManifest(BuildExtensionManifest("File Access", "devtools.html"));
    dir.WriteFile(
        FILE_PATH_LITERAL("devtools.html"),
        "<html><head><script src='devtools.js'></script></head></html>");
    dir.WriteFile(FILE_PATH_LITERAL("devtools.js"),
                  base::StringPrintf(R"(
        chrome.devtools.inspectedWindow.getResources((resources) => {
          const hasFile = !!resources.find(r => r.url.startsWith('file:'));
          setInterval(() => {
            top.postMessage(
                {testOutput: (hasFile == %d) ? 'PASS' : 'FAIL'}, '*');
          }, 10);
        });)",
                                     allow_file_access));

    std::string file_url =
        net::FilePathToFileURL(
            base::PathService::CheckedGet(base::DIR_SOURCE_ROOT)
                .AppendASCII("content/test/data/devtools/navigation.html"))
            .spec();

    const Extension* extension =
        LoadExtensionFromPath(dir.UnpackedPath(), allow_file_access);
    ASSERT_TRUE(extension);

    std::string url = base::StringPrintf(
        R"(data:text/html,<script>//%%23%%20sourceMappingURL=data:application/json,{"version":3,"sources":["%s:%s"]}</script>)",
        url_scheme.c_str(), file_url.c_str() + strlen("file:///"));
    OpenDevToolsWindow(url, false);
    RunTestFunction(window_, "waitForTestResultsAsMessage");
  }
};

IN_PROC_BROWSER_TEST_F(DevToolsExtensionFileAccessTest,
                       CanGetFileResourceWithFileAccess) {
  Run(true, "file:///");
}

IN_PROC_BROWSER_TEST_F(DevToolsExtensionFileAccessTest,
                       CantGetFileResourceWithoutFileAccess) {
  Run(false, "file:///");
}

IN_PROC_BROWSER_TEST_F(DevToolsExtensionFileAccessTest,
                       CantGetFileResourceWithoutFileAccessNoSlashes) {
  Run(false, "file:");
}

IN_PROC_BROWSER_TEST_F(DevToolsExtensionFileAccessTest,
                       CantGetFileResourceWithoutFileAccessMixedCase) {
  Run(false, "fILe:");
}

// Tests that scripts are not duplicated after Scripts Panel switch.
IN_PROC_BROWSER_TEST_F(DevToolsTest, TestNoScriptDuplicatesOnPanelSwitch) {
  RunTest("testNoScriptDuplicatesOnPanelSwitch", kDebuggerTestPage);
}

// Tests that debugger works correctly if pause event occurs when DevTools
// frontend is being loaded.
// Flaky on win and linux: crbug.com/1092924.
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
#define MAYBE_TestPauseWhenLoadingDevTools DISABLED_TestPauseWhenLoadingDevTools
#else
#define MAYBE_TestPauseWhenLoadingDevTools TestPauseWhenLoadingDevTools
#endif
IN_PROC_BROWSER_TEST_F(DevToolsTest, MAYBE_TestPauseWhenLoadingDevTools) {
  RunTest("testPauseWhenLoadingDevTools", kPauseWhenLoadingDevTools);
}

// Tests network timing.
IN_PROC_BROWSER_TEST_F(DevToolsTest, TestNetworkTiming) {
  RunTest("testNetworkTiming", kSlowTestPage);
}

// Tests network size.
IN_PROC_BROWSER_TEST_F(DevToolsTest, TestNetworkSize) {
  RunTest("testNetworkSize", kChunkedTestPage);
}

// Tests raw headers text.
IN_PROC_BROWSER_TEST_F(DevToolsTest, TestNetworkSyncSize) {
  RunTest("testNetworkSyncSize", kChunkedTestPage);
}

namespace {

bool InterceptURLLoad(content::URLLoaderInterceptor::RequestParams* params) {
  const GURL& url = params->url_request.url;
  if (!base::EndsWith(url.path(), kPushTestResource,
                      base::CompareCase::SENSITIVE)) {
    return false;
  }

  auto response = network::mojom::URLResponseHead::New();

  response->headers = new net::HttpResponseHeaders("200 OK\r\n\r\n");

  auto start_time = base::TimeTicks::Now() - base::Milliseconds(10);
  response->request_start = start_time;
  response->response_start = base::TimeTicks::Now();
  response->request_time = base::Time::Now() - base::Milliseconds(10);
  response->response_time = base::Time::Now();

  auto& load_timing = response->load_timing;
  load_timing.request_start = start_time;
  load_timing.request_start_time = response->request_time;
  load_timing.send_start = start_time;
  load_timing.send_end = base::TimeTicks::Now();
  load_timing.receive_headers_end = base::TimeTicks::Now();
  load_timing.push_start = start_time - base::Milliseconds(100);
  if (url.query() != kPushUseNullEndTime) {
    load_timing.push_end = base::TimeTicks::Now();
  }

  // The response's body is empty. The pipe is not filled.
  mojo::ScopedDataPipeProducerHandle producer_handle;
  mojo::ScopedDataPipeConsumerHandle consumer_handle;
  EXPECT_EQ(mojo::CreateDataPipe(nullptr, producer_handle, consumer_handle),
            MOJO_RESULT_OK);
  params->client->OnReceiveResponse(std::move(response),
                                    std::move(consumer_handle), absl::nullopt);
  params->client->OnComplete(network::URLLoaderCompletionStatus());
  return true;
}

}  // namespace

// TODO(crbug.com/1046784) Flaky
IN_PROC_BROWSER_TEST_F(DevToolsTest, DISABLED_TestNetworkPushTime) {
  content::URLLoaderInterceptor interceptor(
      base::BindRepeating(InterceptURLLoad));

  OpenDevToolsWindow(kPushTestPage, false);
  GURL push_url = embedded_test_server()->GetURL(kPushTestResource);

  DispatchOnTestSuite(window_, "testPushTimes", push_url.spec().c_str());

  CloseDevToolsWindow();
}

#if BUILDFLAG(IS_WIN)
// Flaky on Windows: https://crbug.com/1087320
#define MAYBE_TestDOMWarnings DISABLED_TestDOMWarnings
#else
#define MAYBE_TestDOMWarnings TestDOMWarnings
#endif
IN_PROC_BROWSER_TEST_F(DevToolsTest, MAYBE_TestDOMWarnings) {
  RunTest("testDOMWarnings", kDOMWarningsTestPage);
}

// Tests that console messages are not duplicated on navigation back.
#if BUILDFLAG(IS_WIN) || defined(MEMORY_SANITIZER)
// Flaking on windows swarm try runs: crbug.com/409285.
// Also flaking on MSan runs: crbug.com/1182861
#define MAYBE_TestConsoleOnNavigateBack DISABLED_TestConsoleOnNavigateBack
#else
#define MAYBE_TestConsoleOnNavigateBack TestConsoleOnNavigateBack
#endif
IN_PROC_BROWSER_TEST_F(DevToolsTest, MAYBE_TestConsoleOnNavigateBack) {
  RunTest("testConsoleOnNavigateBack", kNavigateBackTestPage);
}

#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
// Flaking on linux runs, see crbug.com/990692.
#define MAYBE_TestDeviceEmulation DISABLED_TestDeviceEmulation
#else
#define MAYBE_TestDeviceEmulation TestDeviceEmulation
#endif
IN_PROC_BROWSER_TEST_F(DevToolsTest, MAYBE_TestDeviceEmulation) {
  RunTest("testDeviceMetricsOverrides", "about:blank");
}

IN_PROC_BROWSER_TEST_F(DevToolsTest, TestDispatchKeyEventDoesNotCrash) {
  RunTest("testDispatchKeyEventDoesNotCrash", "about:blank");
}

class BrowserAutofillManagerTestDelegateDevtoolsImpl
    : public autofill::BrowserAutofillManagerTestDelegate {
 public:
  explicit BrowserAutofillManagerTestDelegateDevtoolsImpl(
      WebContents* inspected_contents)
      : inspected_contents_(inspected_contents) {}

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

  ~BrowserAutofillManagerTestDelegateDevtoolsImpl() override {}

  void DidPreviewFormData() override {}

  void DidFillFormData() override {}

  void DidShowSuggestions() override {
    // Set an override for the minimum 500 ms threshold before enter key strokes
    // are accepted.
    if (base::WeakPtr<autofill::AutofillPopupControllerImpl> controller =
            autofill::ChromeAutofillClient::FromWebContentsForTesting(
                inspected_contents_.get())
                ->popup_controller_for_testing()) {
      controller->DisableThresholdForTesting(true);
    }
    ASSERT_TRUE(content::ExecJs(inspected_contents_,
                                "console.log('didShowSuggestions');"));
  }

  void OnTextFieldChanged() override {}

 private:
  const raw_ptr<WebContents> inspected_contents_;
};

// Disabled. Failing on MacOS MSAN. See https://crbug.com/849129.
// Also failing on Linux. See https://crbug.com/1187693.
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
#define MAYBE_TestDispatchKeyEventShowsAutoFill \
  DISABLED_TestDispatchKeyEventShowsAutoFill
#else
#define MAYBE_TestDispatchKeyEventShowsAutoFill \
  TestDispatchKeyEventShowsAutoFill
#endif
IN_PROC_BROWSER_TEST_F(DevToolsTest, MAYBE_TestDispatchKeyEventShowsAutoFill) {
  OpenDevToolsWindow(kDispatchKeyEventShowsAutoFill, false);
  GetInspectedTab()->Focus();

  autofill::ContentAutofillDriver* autofill_driver =
      autofill::ContentAutofillDriverFactory::FromWebContents(GetInspectedTab())
          ->DriverForFrame(GetInspectedTab()->GetPrimaryMainFrame());
  auto* autofill_manager = static_cast<autofill::BrowserAutofillManager*>(
      autofill_driver->autofill_manager());
  ASSERT_TRUE(autofill_manager);
  BrowserAutofillManagerTestDelegateDevtoolsImpl autoFillTestDelegate(
      GetInspectedTab());
  autofill_manager->SetTestDelegate(&autoFillTestDelegate);

  RunTestFunction(window_, "testDispatchKeyEventShowsAutoFill");
  CloseDevToolsWindow();
}

// Tests that allowed unhandled shortcuts are forwarded from inspected page
// into devtools frontend
IN_PROC_BROWSER_TEST_F(DevToolsTest, testKeyEventUnhandled) {
  OpenDevToolsWindow("about:blank", true);
  RunTestFunction(window_, "testKeyEventUnhandled");
  CloseDevToolsWindow();
}

// Tests that the keys that are forwarded from the browser update
// when their shortcuts change
IN_PROC_BROWSER_TEST_F(DevToolsTest, testForwardedKeysChanged) {
  OpenDevToolsWindow("about:blank", true);
  RunTestFunction(window_, "testForwardedKeysChanged");
  CloseDevToolsWindow();
}

// Test that showing a certificate in devtools does not crash the process.
// Disabled on windows as this opens a modal in its own thread, which leads to a
// test timeout.
#if BUILDFLAG(IS_WIN)
#define MAYBE_testShowCertificate DISABLED_testShowCertificate
#else
#define MAYBE_testShowCertificate testShowCertificate
#endif
IN_PROC_BROWSER_TEST_F(DevToolsTest, MAYBE_testShowCertificate) {
  OpenDevToolsWindow("about:blank", true);
  RunTestFunction(window_, "testShowCertificate");
  CloseDevToolsWindow();
}

// Tests that settings are stored in profile correctly.
IN_PROC_BROWSER_TEST_F(DevToolsTest, TestSettings) {
  OpenDevToolsWindow("about:blank", true);
  RunTestFunction(window_, "testSettings");
  CloseDevToolsWindow();
}

// Tests that external navigation from inspector page is always handled by
// DevToolsWindow and results in inspected page navigation.  See also
// https://crbug.com/180555.
IN_PROC_BROWSER_TEST_F(DevToolsTest, TestDevToolsExternalNavigation) {
  OpenDevToolsWindow(kDebuggerTestPage, true);
  GURL url = embedded_test_server()->GetURL(kNavigateBackTestPage);
  ui_test_utils::UrlLoadObserver observer(
      url, content::NotificationService::AllSources());
  ASSERT_TRUE(
      content::ExecJs(main_web_contents(),
                      std::string("window.location = \"") + url.spec() + "\""));
  observer.Wait();

  ASSERT_TRUE(main_web_contents()->GetLastCommittedURL().SchemeIs(
      content::kChromeDevToolsScheme));
  ASSERT_EQ(url, GetInspectedTab()->GetLastCommittedURL());
  CloseDevToolsWindow();
}

// Tests that toolbox window is loaded when DevTools window is undocked.
IN_PROC_BROWSER_TEST_F(DevToolsTest, TestToolboxLoadedUndocked) {
  OpenDevToolsWindow(kDebuggerTestPage, false);
  ASSERT_TRUE(toolbox_web_contents());
  DevToolsWindow* on_self =
      DevToolsWindowTesting::OpenDevToolsWindowSync(main_web_contents(), false);
  EXPECT_FALSE(DevToolsWindowTesting::Get(on_self)->toolbox_web_contents());
  DevToolsWindowTesting::CloseDevToolsWindowSync(on_self);
  CloseDevToolsWindow();
}

// Tests that toolbox window is not loaded when DevTools window is docked.
// TODO(crbug.com/1320168): Re-enable this test
IN_PROC_BROWSER_TEST_F(DevToolsTest, DISABLED_TestToolboxNotLoadedDocked) {
  OpenDevToolsWindow(kDebuggerTestPage, true);
  EXPECT_FALSE(toolbox_web_contents());
  DevToolsWindow* on_self =
      DevToolsWindowTesting::OpenDevToolsWindowSync(main_web_contents(), false);
  EXPECT_FALSE(DevToolsWindowTesting::Get(on_self)->toolbox_web_contents());
  DevToolsWindowTesting::CloseDevToolsWindowSync(on_self);
  CloseDevToolsWindow();
}

// Tests that inspector will reattach to inspected page when it is reloaded
// after a crash. See http://crbug.com/101952
// Disabled. it doesn't check anything right now: http://crbug.com/461790
IN_PROC_BROWSER_TEST_F(DevToolsTest, DISABLED_TestReattachAfterCrash) {
  RunTest("testReattachAfterCrash", kArbitraryPage);
}

IN_PROC_BROWSER_TEST_F(DevToolsTest, TestPageWithNoJavaScript) {
  OpenDevToolsWindow("about:blank", false);
  std::string result;
  ASSERT_EQ(
      "function",
      content::EvalJs(
          main_web_contents(),
          "'' + (window.uiTests && (typeof uiTests.dispatchOnTestSuite));"))
      << "DevTools front-end is broken.";
  CloseDevToolsWindow();
}

class DevToolsAutoOpenerTest : public DevToolsTest {
 public:
  void SetUpCommandLine(base::CommandLine* command_line) override {
    command_line->AppendSwitch(switches::kAutoOpenDevToolsForTabs);
    observer_ = std::make_unique<DevToolsWindowCreationObserver>();
  }

 protected:
  std::unique_ptr<DevToolsWindowCreationObserver> observer_;
};

// TODO(https://crbug.com/1167158): Flaky on debug builds.
#if !defined(NDEBUG)
#define MAYBE_TestAutoOpenForTabs DISABLED_TestAutoOpenForTabs
#elif BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX)
// TODO(https://crbug.com/1289330): Flaky failures
#define MAYBE_TestAutoOpenForTabs DISABLED_TestAutoOpenForTabs
#else
#define MAYBE_TestAutoOpenForTabs TestAutoOpenForTabs
#endif
IN_PROC_BROWSER_TEST_F(DevToolsAutoOpenerTest, MAYBE_TestAutoOpenForTabs) {
  {
    DevToolsWindowCreationObserver observer;
    ASSERT_TRUE(AddTabAtIndexToBrowser(browser(), 0, GURL("about:blank"),
                                       ui::PAGE_TRANSITION_AUTO_TOPLEVEL,
                                       false));
    observer.WaitForLoad();
  }
  Browser* new_browser = nullptr;
  {
    DevToolsWindowCreationObserver observer;
    new_browser = CreateBrowser(browser()->profile());
    observer.WaitForLoad();
  }
  {
    DevToolsWindowCreationObserver observer;
    ASSERT_TRUE(AddTabAtIndexToBrowser(new_browser, 0, GURL("about:blank"),
                                       ui::PAGE_TRANSITION_AUTO_TOPLEVEL,
                                       false));
    observer.WaitForLoad();
  }
  observer_->CloseAllSync();
}

class DevToolsReattachAfterCrashTest : public DevToolsTest {
 protected:
  void RunTestWithPanel(const char* panel_name) {
    OpenDevToolsWindow("about:blank", false);
    SwitchToPanel(window_, panel_name);
    ASSERT_TRUE(
        ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL)));

    content::RenderProcessHostWatcher crash_observer(
        GetInspectedTab(),
        content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
    ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(),
                                             GURL(blink::kChromeUICrashURL)));
    crash_observer.Wait();
    content::TestNavigationObserver navigation_observer(GetInspectedTab(), 1);
    chrome::Reload(browser(), WindowOpenDisposition::CURRENT_TAB);
    navigation_observer.Wait();
  }
};

IN_PROC_BROWSER_TEST_F(DevToolsReattachAfterCrashTest,
                       TestReattachAfterCrashOnTimeline) {
  RunTestWithPanel("timeline");
}

IN_PROC_BROWSER_TEST_F(DevToolsReattachAfterCrashTest,
                       TestReattachAfterCrashOnNetwork) {
  RunTestWithPanel("network");
}

// Very flaky on Linux only.  http://crbug.com/1216219
#if BUILDFLAG(IS_LINUX)
#define MAYBE_AutoAttachToWindowOpen DISABLED_AutoAttachToWindowOpen
#else
#define MAYBE_AutoAttachToWindowOpen AutoAttachToWindowOpen
#endif
IN_PROC_BROWSER_TEST_F(DevToolsTest, MAYBE_AutoAttachToWindowOpen) {
  OpenDevToolsWindow(kWindowOpenTestPage, false);
  DevToolsWindowTesting::Get(window_)->SetOpenNewWindowForPopups(true);
  DevToolsWindowCreationObserver observer;
  ASSERT_TRUE(content::ExecJs(GetInspectedTab(),
                              "window.open('window_open.html', '_blank');"));
  observer.WaitForLoad();
  DispatchOnTestSuite(observer.devtools_window(), "waitForDebuggerPaused");
  DevToolsWindowTesting::CloseDevToolsWindowSync(observer.devtools_window());
  CloseDevToolsWindow();
}

// TODO(crbug.com/1102964) Flaky
IN_PROC_BROWSER_TEST_F(DevToolsTest, DISABLED_SecondTabAfterDevTools) {
  OpenDevToolsWindow(kDebuggerTestPage, true);

  ui_test_utils::NavigateToURLWithDisposition(
      browser(), embedded_test_server()->GetURL(kDebuggerTestPage),
      WindowOpenDisposition::NEW_FOREGROUND_TAB,
      ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB |
          ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
  WebContents* second = browser()->tab_strip_model()->GetActiveWebContents();

  scoped_refptr<content::DevToolsAgentHost> agent(
      GetOrCreateDevToolsHostForWebContents(second));
  EXPECT_EQ("page", agent->GetType());

  CloseDevToolsWindow();
}

IN_PROC_BROWSER_TEST_F(WorkerDevToolsTest, InspectSharedWorker) {
  GURL url = embedded_test_server()->GetURL(kSharedWorkerTestPage);
  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));

  scoped_refptr<DevToolsAgentHost> host =
      WaitForFirstSharedWorker(kSharedWorkerTestWorker);
  OpenDevToolsWindow(host);
  RunTestFunction(window_, "testSharedWorker");
  CloseDevToolsWindow();
}

// Flaky on multiple platforms. See http://crbug.com/1263230
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \
    BUILDFLAG(IS_MAC) || BUILDFLAG(IS_FUCHSIA)
#define MAYBE_PauseInSharedWorkerInitialization \
  DISABLED_PauseInSharedWorkerInitialization
#else
#define MAYBE_PauseInSharedWorkerInitialization \
  PauseInSharedWorkerInitialization
#endif
IN_PROC_BROWSER_TEST_F(WorkerDevToolsTest,
                       MAYBE_PauseInSharedWorkerInitialization) {
  GURL url = embedded_test_server()->GetURL(kReloadSharedWorkerTestPage);
  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));

  scoped_refptr<DevToolsAgentHost> host =
      WaitForFirstSharedWorker(kReloadSharedWorkerTestWorker);
  OpenDevToolsWindow(host);

  // We should make sure that the worker inspector has loaded before
  // terminating worker.
  RunTestFunction(window_, "testPauseInSharedWorkerInitialization1");

  host->Close();

  // Reload page to restart the worker.
  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));

  // Wait until worker script is paused on the debugger statement.
  RunTestFunction(window_, "testPauseInSharedWorkerInitialization2");
  CloseDevToolsWindow();
}

class DevToolsAgentHostTest : public InProcessBrowserTest {};

// Tests DevToolsAgentHost retention by its target.
IN_PROC_BROWSER_TEST_F(DevToolsAgentHostTest, TestAgentHostReleased) {
  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL("about:blank")));
  WebContents* web_contents = browser()->tab_strip_model()->GetWebContentsAt(0);
  DevToolsAgentHost* agent_raw =
      DevToolsAgentHost::GetOrCreateFor(web_contents).get();
  const std::string agent_id = agent_raw->GetId();
  ASSERT_EQ(agent_raw, DevToolsAgentHost::GetForId(agent_id).get())
      << "DevToolsAgentHost cannot be found by id";
  browser()->tab_strip_model()->CloseWebContentsAt(0,
                                                   TabCloseTypes::CLOSE_NONE);
  EXPECT_FALSE(DevToolsAgentHost::GetForId(agent_id).get())
      << "DevToolsAgentHost is not released when the tab is closed";
}

class RemoteDebuggingTest : public extensions::ExtensionApiTest {
  void SetUpCommandLine(base::CommandLine* command_line) override {
    extensions::ExtensionApiTest::SetUpCommandLine(command_line);
    command_line->AppendSwitchASCII(switches::kRemoteDebuggingPort, "9222");
    command_line->AppendSwitchASCII(switches::kRemoteAllowOrigins, "*");

    // Override the extension root path.
    base::PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_);
    test_data_dir_ = test_data_dir_.AppendASCII("devtools");
  }
};

// Fails on CrOS. crbug.com/431399
#if BUILDFLAG(IS_CHROMEOS_ASH)
#define MAYBE_RemoteDebugger DISABLED_RemoteDebugger
#else
// TODO(crbug.com/997911): Flaky on all platforms.
#define MAYBE_RemoteDebugger DISABLED_RemoteDebugger
#endif
IN_PROC_BROWSER_TEST_F(RemoteDebuggingTest, MAYBE_RemoteDebugger) {
  ASSERT_TRUE(RunExtensionTest("target_list")) << message_;
}

IN_PROC_BROWSER_TEST_F(RemoteDebuggingTest, DiscoveryPage) {
  ASSERT_TRUE(RunExtensionTest("discovery_page")) << message_;
}

IN_PROC_BROWSER_TEST_F(DevToolsTest, PolicyDisallowed) {
  DisallowDevTools(browser());
  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL("about:blank")));
  content::WebContents* web_contents =
      browser()->tab_strip_model()->GetWebContentsAt(0);
  DevToolsWindow::OpenDevToolsWindow(web_contents);
  auto agent_host = GetOrCreateDevToolsHostForWebContents(web_contents);
  EXPECT_FALSE(DevToolsWindow::FindDevToolsWindow(agent_host.get()));
}

IN_PROC_BROWSER_TEST_F(DevToolsTest, PolicyDisallowedCloseConnection) {
  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL("about:blank")));
  content::WebContents* web_contents =
      browser()->tab_strip_model()->GetWebContentsAt(0);
  DevToolsWindow::OpenDevToolsWindow(web_contents);
  auto agent_host = GetOrCreateDevToolsHostForWebContents(web_contents);

  // Policy change must close the connection
  DisallowDevTools(browser());
  EXPECT_FALSE(DevToolsWindow::FindDevToolsWindow(agent_host.get()));
}

using ManifestLocation = extensions::mojom::ManifestLocation;
class DevToolsDisallowedForForceInstalledExtensionsPolicyTest
    : public extensions::ExtensionBrowserTest {
 public:
  // Installs an extensions, using the specified manifest location.
  // Contains assertions - callers should wrap calls of this method in
  // |ASSERT_NO_FATAL_FAILURE|.
  void InstallExtensionWithLocation(ManifestLocation location,
                                    std::string* extension_id) {
    base::FilePath crx_path;
    base::PathService::Get(chrome::DIR_TEST_DATA, &crx_path);
    crx_path = crx_path.AppendASCII("devtools")
                   .AppendASCII("extensions")
                   .AppendASCII("options.crx");
    const Extension* extension = InstallExtension(crx_path, 1, location);
    ASSERT_TRUE(extension);
    *extension_id = extension->id();
  }

  // Same as above, but also fills |*out_web_contents| with a |WebContents|
  // that has been navigated to the installed extension.
  void InstallExtensionAndOpen(ManifestLocation location,
                               content::WebContents** out_web_contents) {
    std::string extension_id;
    InstallExtensionWithLocation(location, &extension_id);
    GURL url("chrome-extension://" + extension_id + "/options.html");
    ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
    *out_web_contents = browser()->tab_strip_model()->GetWebContentsAt(0);
  }

  void PolicyInstallExtensionAndOpen(content::WebContents** out_web_contents) {
    InstallExtensionAndOpen(ManifestLocation::kExternalPolicyDownload,
                            out_web_contents);
  }

  void InstallComponentExtensionAndOpen(
      content::WebContents** out_web_contents) {
    InstallExtensionAndOpen(ManifestLocation::kExternalComponent,
                            out_web_contents);
  }
};

IN_PROC_BROWSER_TEST_F(DevToolsDisallowedForForceInstalledExtensionsPolicyTest,
                       DisallowedForExternalPolicyDownloadExtension) {
  // DevTools are disallowed for policy-installed extensions by default.
  content::WebContents* web_contents = nullptr;
  ASSERT_NO_FATAL_FAILURE(PolicyInstallExtensionAndOpen(&web_contents));

  DevToolsWindow::OpenDevToolsWindow(web_contents);
  auto agent_host = GetOrCreateDevToolsHostForWebContents(web_contents);
  EXPECT_FALSE(DevToolsWindow::FindDevToolsWindow(agent_host.get()));
}

IN_PROC_BROWSER_TEST_F(DevToolsDisallowedForForceInstalledExtensionsPolicyTest,
                       DisallowedForComponentExtensionForManagedUsers) {
  // DevTools are disallowed for component extensions by default for managed
  // profiles.
  profile()->GetProfilePolicyConnector()->OverrideIsManagedForTesting(true);
  content::WebContents* web_contents = nullptr;
  ASSERT_NO_FATAL_FAILURE(InstallComponentExtensionAndOpen(&web_contents));

  DevToolsWindow::OpenDevToolsWindow(web_contents);
  auto agent_host = GetOrCreateDevToolsHostForWebContents(web_contents);
  EXPECT_FALSE(DevToolsWindow::FindDevToolsWindow(agent_host.get()));
}

IN_PROC_BROWSER_TEST_F(DevToolsDisallowedForForceInstalledExtensionsPolicyTest,
                       AllowedForComponentExtensionForNonManagedUsers) {
  // DevTools are allowed for component extensions by default non-managed
  // profiles.
  content::WebContents* web_contents = nullptr;
  ASSERT_NO_FATAL_FAILURE(InstallComponentExtensionAndOpen(&web_contents));

  DevToolsWindow::OpenDevToolsWindow(web_contents);
  auto agent_host = GetOrCreateDevToolsHostForWebContents(web_contents);
  ASSERT_TRUE(DevToolsWindow::FindDevToolsWindow(agent_host.get()));
}

IN_PROC_BROWSER_TEST_F(DevToolsDisallowedForForceInstalledExtensionsPolicyTest,
                       ExtensionConnectionClosedOnPolicyChange) {
  AllowDevTools(browser());
  content::WebContents* web_contents = nullptr;
  ASSERT_NO_FATAL_FAILURE(PolicyInstallExtensionAndOpen(&web_contents));

  DevToolsWindow::OpenDevToolsWindow(web_contents);
  auto agent_host = GetOrCreateDevToolsHostForWebContents(web_contents);

  ASSERT_TRUE(DevToolsWindow::FindDevToolsWindow(agent_host.get()));

  // Policy change must close the connection with the policy installed
  // extension.
  DisallowDevToolsForForceInstalledExtenions(browser());
  EXPECT_FALSE(DevToolsWindow::FindDevToolsWindow(agent_host.get()));
}

IN_PROC_BROWSER_TEST_F(DevToolsDisallowedForForceInstalledExtensionsPolicyTest,
                       ClosedAfterNavigationToExtension) {
  // DevTools are disallowed for policy-installed extensions by default.
  std::string extension_id;
  ASSERT_NO_FATAL_FAILURE(InstallExtensionWithLocation(
      ManifestLocation::kExternalPolicyDownload, &extension_id));
  content::WebContents* web_contents =
      browser()->tab_strip_model()->GetWebContentsAt(0);

  // It's possible to open DevTools for about:blank.
  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL("about:blank")));
  DevToolsWindow::OpenDevToolsWindow(web_contents);
  auto agent_host = GetOrCreateDevToolsHostForWebContents(web_contents);
  ASSERT_TRUE(DevToolsWindow::FindDevToolsWindow(agent_host.get()));

  // Navigating to extension page should close DevTools.
  ASSERT_TRUE(ui_test_utils::NavigateToURL(
      browser(), GURL("chrome-extension://" + extension_id + "/options.html")));
  EXPECT_FALSE(DevToolsWindow::FindDevToolsWindow(agent_host.get()));
}

IN_PROC_BROWSER_TEST_F(DevToolsDisallowedForForceInstalledExtensionsPolicyTest,
                       AboutBlankConnectionKeptOnPolicyChange) {
  AllowDevTools(browser());

  std::string extension_id;
  ASSERT_NO_FATAL_FAILURE(InstallExtensionWithLocation(
      ManifestLocation::kExternalPolicyDownload, &extension_id));
  content::WebContents* web_contents =
      browser()->tab_strip_model()->GetWebContentsAt(0);

  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL("about:blank")));
  DevToolsWindow::OpenDevToolsWindow(web_contents);
  auto agent_host = GetOrCreateDevToolsHostForWebContents(web_contents);
  ASSERT_TRUE(DevToolsWindow::FindDevToolsWindow(agent_host.get()));

  // Policy change to must not disrupt CDP coneciton unrelated to a force
  // installed extension.
  DisallowDevToolsForForceInstalledExtenions(browser());
  ASSERT_TRUE(DevToolsWindow::FindDevToolsWindow(agent_host.get()));
}

class DevToolsAllowedByCommandLineSwitch
    : public DevToolsDisallowedForForceInstalledExtensionsPolicyTest {
 public:
  void SetUpCommandLine(base::CommandLine* command_line) override {
    extensions::ExtensionBrowserTest::SetUpCommandLine(command_line);
    // Same as `switches::kForceDevToolsAvailable`, but used as a
    // literal here so it's possible to verify that the switch does not apply on
    // non-ChromeOS platforms.
    const std::string kForceDevToolsAvailableBase = "force-devtools-available";
#if BUILDFLAG(IS_CHROMEOS)
    ASSERT_EQ(kForceDevToolsAvailableBase, switches::kForceDevToolsAvailable);
#endif
    command_line->AppendSwitch("--" + kForceDevToolsAvailableBase);
  }
};

IN_PROC_BROWSER_TEST_F(DevToolsAllowedByCommandLineSwitch,
                       SwitchOverridesPolicyOnChromeOS) {
  // DevTools are disallowed for policy-installed extensions by default.
  content::WebContents* web_contents = nullptr;
  ASSERT_NO_FATAL_FAILURE(PolicyInstallExtensionAndOpen(&web_contents));

  DevToolsWindow::OpenDevToolsWindow(web_contents);
  auto agent_host = GetOrCreateDevToolsHostForWebContents(web_contents);
#if BUILDFLAG(IS_CHROMEOS)
  EXPECT_TRUE(DevToolsWindow::FindDevToolsWindow(agent_host.get()));
#else
  EXPECT_FALSE(DevToolsWindow::FindDevToolsWindow(agent_host.get()));
#endif
}

class DevToolsPixelOutputTests : public DevToolsTest {
 public:
  void SetUp() override {
    EnablePixelOutput();
    DevToolsTest::SetUp();
  }
  void SetUpCommandLine(base::CommandLine* command_line) override {
    command_line->AppendSwitch(switches::kUseGpuInTests);
  }
};

// This test enables switches::kUseGpuInTests which causes false positives
// with MemorySanitizer. This is also flakey on many configurations.
// See https://crbug.com/510291
IN_PROC_BROWSER_TEST_F(DevToolsPixelOutputTests,
                       DISABLED_TestScreenshotRecording) {
  RunTest("testScreenshotRecording", kArbitraryPage);
}

// This test enables switches::kUseGpuInTests which causes false positives
// with MemorySanitizer.
// Flaky on multiple platforms https://crbug.com/624215
IN_PROC_BROWSER_TEST_F(DevToolsPixelOutputTests,
                       DISABLED_TestLatencyInfoInstrumentation) {
  WebContents* web_contents = GetInspectedTab();
  OpenDevToolsWindow(kLatencyInfoTestPage, false);
  DispatchAndWait("startTimeline");

  for (int i = 0; i < 3; ++i) {
    SimulateMouseEvent(web_contents, blink::WebInputEvent::Type::kMouseMove,
                       gfx::Point(30, 60));
    DispatchInPageAndWait("waitForEvent", "mousemove");
  }

  SimulateMouseClickAt(web_contents, 0,
                       blink::WebPointerProperties::Button::kLeft,
                       gfx::Point(30, 60));
  DispatchInPageAndWait("waitForEvent", "click");

  SimulateMouseWheelEvent(web_contents, gfx::Point(300, 100),
                          gfx::Vector2d(0, 120),
                          blink::WebMouseWheelEvent::kPhaseBegan);
  DispatchInPageAndWait("waitForEvent", "wheel");

  SimulateTapAt(web_contents, gfx::Point(30, 60));
  DispatchInPageAndWait("waitForEvent", "gesturetap");

  DispatchAndWait("stopTimeline");
  RunTestMethod("checkInputEventsPresent", "MouseMove", "MouseDown",
                "MouseWheel", "GestureTap");

  CloseDevToolsWindow();
}

class DevToolsNetInfoTest : public DevToolsTest {
 protected:
  void SetUpCommandLine(base::CommandLine* command_line) override {
    command_line->AppendSwitch(switches::kEnableNetworkInformationDownlinkMax);
    command_line->AppendSwitch(
        switches::kEnableExperimentalWebPlatformFeatures);
  }
};

IN_PROC_BROWSER_TEST_F(DevToolsNetInfoTest, EmulateNetworkConditions) {
  RunTest("testEmulateNetworkConditions", kEmulateNetworkConditionsPage);
}

IN_PROC_BROWSER_TEST_F(DevToolsNetInfoTest, OfflineNetworkConditions) {
  RunTest("testOfflineNetworkConditions", kEmulateNetworkConditionsPage);
}

class StaticURLDataSource : public content::URLDataSource {
 public:
  StaticURLDataSource(const std::string& source, const std::string& content)
      : source_(source), content_(content) {}

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

  ~StaticURLDataSource() override = default;

  // content::URLDataSource:
  std::string GetSource() override { return source_; }
  void StartDataRequest(const GURL& url,
                        const content::WebContents::Getter& wc_getter,
                        GotDataCallback callback) override {
    std::move(callback).Run(
        base::MakeRefCounted<base::RefCountedString>(std::string(content_)));
  }
  std::string GetMimeType(const GURL& url) override { return "text/html"; }
  bool ShouldAddContentSecurityPolicy() override { return false; }

 private:
  const std::string source_;
  const std::string content_;
};

class MockWebUIProvider
    : public TestChromeWebUIControllerFactory::WebUIProvider {
 public:
  MockWebUIProvider(const std::string& source, const std::string& content)
      : source_(source), content_(content) {}

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

  ~MockWebUIProvider() override = default;

  std::unique_ptr<content::WebUIController> NewWebUI(content::WebUI* web_ui,
                                                     const GURL& url) override {
    content::URLDataSource::Add(
        Profile::FromWebUI(web_ui),
        std::make_unique<StaticURLDataSource>(source_, content_));
    return std::make_unique<content::WebUIController>(web_ui);
  }

 private:
  std::string source_;
  std::string content_;
};

// This tests checks that window is correctly initialized when DevTools is
// opened while navigation through history with forward and back actions.
// (crbug.com/627407)
// TODO(https://crbug.com/1443360): Deflake and re-enable this test.
IN_PROC_BROWSER_TEST_F(DevToolsTest,
                       DISABLED_TestWindowInitializedOnNavigateBack) {
  TestChromeWebUIControllerFactory test_factory;
  content::ScopedWebUIControllerFactoryRegistration factory_registration(
      &test_factory);
  MockWebUIProvider mock_provider("dummyurl",
                                  "<script>\n"
                                  "  window.abc = 239;\n"
                                  "  console.log(abc);\n"
                                  "</script>");
  test_factory.AddFactoryOverride(GURL("chrome://foo/dummyurl").host(),
                                  &mock_provider);

  ASSERT_TRUE(
      ui_test_utils::NavigateToURL(browser(), GURL("chrome://foo/dummyurl")));
  DevToolsWindow* window =
      DevToolsWindowTesting::OpenDevToolsWindowSync(GetInspectedTab(), true);
  chrome::DuplicateTab(browser());
  chrome::SelectPreviousTab(browser());
  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL("about:blank")));
  chrome::GoBack(browser(), WindowOpenDisposition::CURRENT_TAB);
  RunTestFunction(window, "testWindowInitializedOnNavigateBack");

  DevToolsWindowTesting::CloseDevToolsWindowSync(window);
}

IN_PROC_BROWSER_TEST_F(DevToolsTest, TestRawHeadersWithRedirectAndHSTS) {
  net::EmbeddedTestServer https_test_server(
      net::EmbeddedTestServer::TYPE_HTTPS);
  https_test_server.SetSSLConfig(
      net::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN);
  https_test_server.ServeFilesFromSourceDirectory(GetChromeTestDataDir());
  ASSERT_TRUE(https_test_server.Start());
  GURL https_url = https_test_server.GetURL("localhost", "/devtools/image.png");
  base::Time expiry = base::Time::Now() + base::Days(1000);
  bool include_subdomains = false;
  mojo::ScopedAllowSyncCallForTesting allow_sync_call;
  content::StoragePartition* partition =
      browser()->profile()->GetDefaultStoragePartition();
  base::RunLoop run_loop;
  partition->GetNetworkContext()->AddHSTS(
      https_url.host(), expiry, include_subdomains, run_loop.QuitClosure());
  run_loop.Run();

  OpenDevToolsWindow(kArbitraryPage, false);

  net::EmbeddedTestServer test_server2;
  test_server2.AddDefaultHandlers();
  ASSERT_TRUE(test_server2.Start());
  GURL::Replacements replace_scheme;
  replace_scheme.SetSchemeStr("http");
  GURL http_url = https_url.ReplaceComponents(replace_scheme);
  GURL redirect_url =
      test_server2.GetURL("/server-redirect?" + http_url.spec());

  DispatchOnTestSuite(window_, "testRawHeadersWithHSTS",
                      redirect_url.spec().c_str());
  CloseDevToolsWindow();
}

// Tests that OpenInNewTab filters URLs.
// TODO(https://crbug.com/1335516): Flaky on Windows and Linux.
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX)
#define MAYBE_TestOpenInNewTabFilter DISABLED_TestOpenInNewTabFilter
#else
#define MAYBE_TestOpenInNewTabFilter TestOpenInNewTabFilter
#endif
IN_PROC_BROWSER_TEST_F(DevToolsTest, MAYBE_TestOpenInNewTabFilter) {
  OpenDevToolsWindow(kDebuggerTestPage, false);
  DevToolsUIBindings::Delegate* bindings_delegate_ =
      static_cast<DevToolsUIBindings::Delegate*>(window_);
  std::string test_url =
      embedded_test_server()->GetURL(kDebuggerTestPage).spec();
  const std::string self_blob_url =
      base::StringPrintf("blob:%s", test_url.c_str());
  const std::string self_filesystem_url =
      base::StringPrintf("filesystem:%s", test_url.c_str());

  // Pairs include a URL string and boolean whether it should be allowed.
  std::vector<std::pair<const std::string, const std::string>> tests = {
      {test_url, test_url},
      {"data:,foo", "data:,foo"},
      {"about://inspect", "about:blank"},
      {"chrome://inspect", "about:blank"},
      {"chrome://inspect/#devices", "about:blank"},
      {self_blob_url, self_blob_url},
      {"blob:chrome://inspect", "about:blank"},
      {self_filesystem_url, self_filesystem_url},
      {"filesystem:chrome://inspect", "about:blank"},
      {"view-source:http://chromium.org", "about:blank"},
      {"file:///", "about:blank"},
      {"about://gpu", "about:blank"},
      {"chrome://gpu", "about:blank"},
      {"chrome://crash", "about:blank"},
      {"", "about:blank"},
  };

  TabStripModel* tabs = browser()->tab_strip_model();
  int i = 0;
  for (const std::pair<const std::string, const std::string>& pair : tests) {
    bindings_delegate_->OpenInNewTab(pair.first);
    i++;

    std::string opened_url = tabs->GetWebContentsAt(i)->GetVisibleURL().spec();
    SCOPED_TRACE(
        base::StringPrintf("while testing URL: %s", pair.first.c_str()));
    EXPECT_EQ(opened_url, pair.second);
  }

  CloseDevToolsWindow();
}

IN_PROC_BROWSER_TEST_F(DevToolsTest, LoadNetworkResourceForFrontend) {
  std::string file_url =
      "file://" + base::PathService::CheckedGet(base::DIR_SOURCE_ROOT)
                      .AppendASCII("content/test/data/devtools/navigation.html")
                      .NormalizePathSeparatorsTo('/')
                      .AsUTF8Unsafe();

  GURL url(embedded_test_server()->GetURL("/"));
  ASSERT_TRUE(ui_test_utils::NavigateToURL(
      browser(), embedded_test_server()->GetURL("/hello.html")));
  window_ =
      DevToolsWindowTesting::OpenDevToolsWindowSync(GetInspectedTab(), false);
  LoadLegacyFilesInFrontend(window_);
  RunTestMethod("testLoadResourceForFrontend", url.spec().c_str(),
                file_url.c_str());
  DevToolsWindowTesting::CloseDevToolsWindowSync(window_);
}

// TODO(crbug.com/921608) Disabled for flakiness.
IN_PROC_BROWSER_TEST_F(DevToolsTest, DISABLED_CreateBrowserContext) {
  GURL url(embedded_test_server()->GetURL("/devtools/empty.html"));
  window_ = DevToolsWindowTesting::OpenDiscoveryDevToolsWindowSync(
      browser()->profile());
  RunTestMethod("testCreateBrowserContext", url.spec().c_str());
  DevToolsWindowTesting::CloseDevToolsWindowSync(window_);
}

// TODO(crbug.com/1110417): Flaky.
IN_PROC_BROWSER_TEST_F(DevToolsTest, DISABLED_DisposeEmptyBrowserContext) {
  window_ = DevToolsWindowTesting::OpenDiscoveryDevToolsWindowSync(
      browser()->profile());
  RunTestMethod("testDisposeEmptyBrowserContext");
  DevToolsWindowTesting::CloseDevToolsWindowSync(window_);
}

// TODO(1078348): Find a better strategy for testing protocol methods against
// non-headless Chrome.
IN_PROC_BROWSER_TEST_F(DevToolsTest, NewWindowFromBrowserContext) {
  window_ = DevToolsWindowTesting::OpenDiscoveryDevToolsWindowSync(
      browser()->profile());
  LoadLegacyFilesInFrontend(window_);
  RunTestMethod("testNewWindowFromBrowserContext");
  DevToolsWindowTesting::CloseDevToolsWindowSync(window_);
}

IN_PROC_BROWSER_TEST_F(SitePerProcessDevToolsTest, InspectElement) {
  GURL url(embedded_test_server()->GetURL("a.com", "/devtools/oopif.html"));
  GURL iframe_url(
      embedded_test_server()->GetURL("b.com", "/devtools/oopif_frame.html"));

  WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();

  content::TestNavigationManager navigation_manager(tab, url);
  content::TestNavigationManager navigation_manager_iframe(tab, iframe_url);

  tab->GetController().LoadURL(url, content::Referrer(),
                               ui::PAGE_TRANSITION_LINK, std::string());

  ASSERT_TRUE(navigation_manager.WaitForNavigationFinished());
  ASSERT_TRUE(navigation_manager_iframe.WaitForNavigationFinished());
  EXPECT_TRUE(content::WaitForLoadStop(tab));

  std::vector<RenderFrameHost*> frames =
      CollectAllRenderFrameHosts(GetInspectedTab());
  ASSERT_EQ(2u, frames.size());
  ASSERT_NE(frames[0]->GetProcess(), frames[1]->GetProcess());
  RenderFrameHost* frame_host = frames[0]->GetParent() ? frames[0] : frames[1];

  DevToolsWindowCreationObserver observer;
  DevToolsWindow::InspectElement(frame_host, 100, 100);
  observer.WaitForLoad();
  DevToolsWindow* window = observer.devtools_window();

  DispatchOnTestSuite(window, "testInspectedElementIs", "INSPECTED-DIV");
  DevToolsWindowTesting::CloseDevToolsWindowSync(window);
}

class DevToolsTabTargetTest : public DevToolsTest {
  base::test::ScopedFeatureList scoped_feature_list_{
      ::features::kDevToolsTabTarget};
};

IN_PROC_BROWSER_TEST_F(DevToolsTabTargetTest, InspectElement) {
  GURL url(
      embedded_test_server()->GetURL("a.com", "/devtools/oopif_frame.html"));

  WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();

  content::TestNavigationManager navigation_manager(tab, url);

  tab->GetController().LoadURL(url, content::Referrer(),
                               ui::PAGE_TRANSITION_LINK, std::string());

  ASSERT_TRUE(navigation_manager.WaitForNavigationFinished());
  EXPECT_TRUE(content::WaitForLoadStop(tab));

  std::vector<RenderFrameHost*> frames =
      CollectAllRenderFrameHosts(GetInspectedTab());
  ASSERT_EQ(1u, frames.size());
  RenderFrameHost* frame_host = frames[0];

  DevToolsWindowCreationObserver observer;
  DevToolsWindow::InspectElement(frame_host, 100, 100);
  observer.WaitForLoad();
  DevToolsWindow* window = observer.devtools_window();

  DispatchOnTestSuite(window, "testInspectedElementIs", "INSPECTED-DIV");
  DevToolsWindowTesting::CloseDevToolsWindowSync(window);
}

IN_PROC_BROWSER_TEST_F(DevToolsTest, ExistsForWebContentsAfterClosing) {
  EXPECT_FALSE(content::DevToolsAgentHost::HasFor(GetInspectedTab()));

  // Simulate opening devtools for the current tab.
  OpenDevToolsWindow(kDebuggerTestPage, true);
  ASSERT_TRUE(content::DevToolsAgentHost::HasFor(GetInspectedTab()));

  // Closes devtools window for the current tab i.e. exit the devtools
  // inspector.
  CloseDevToolsWindow();

  // The devtools window instance still exists for the current tab even though
  // it is now closed.
  ASSERT_TRUE(content::DevToolsAgentHost::HasFor(GetInspectedTab()));
}

IN_PROC_BROWSER_TEST_F(InProcessBrowserTest, BrowserCloseWithBeforeUnload) {
  EXPECT_FALSE(KeepAliveRegistry::GetInstance()->IsOriginRegistered(
      KeepAliveOrigin::REMOTE_DEBUGGING));
  ASSERT_TRUE(
      ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL)));
  WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
  ASSERT_TRUE(
      content::ExecJs(tab,
                      "window.addEventListener('beforeunload',"
                      "function(event) { event.returnValue = 'Foo'; });"));
  content::PrepContentsForBeforeUnloadTest(tab);
  BrowserHandler handler(nullptr, std::string());
  handler.Close();
  ui_test_utils::WaitForBrowserToClose(browser());
}

// Flaky.
// TODO(https://crbug.com/1132296): Re-enable.
IN_PROC_BROWSER_TEST_F(InProcessBrowserTest,
                       DISABLED_BrowserCloseWithContextMenuOpened) {
  EXPECT_FALSE(KeepAliveRegistry::GetInstance()->IsOriginRegistered(
      KeepAliveOrigin::REMOTE_DEBUGGING));
  ASSERT_TRUE(
      ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL)));
  auto callback = [](RenderViewContextMenu* context_menu) {
    BrowserHandler handler(nullptr, std::string());
    handler.Close();
  };
  WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
  RenderViewContextMenu::RegisterMenuShownCallbackForTesting(
      base::BindOnce(callback));
  content::SimulateMouseClickAt(tab, 0, blink::WebMouseEvent::Button::kRight,
                                gfx::Point(15, 15));
  ui_test_utils::WaitForBrowserToClose(browser());
}

#if !BUILDFLAG(IS_CHROMEOS)
// Skip for ChromeOS because the keep alive is not created for ChromeOS.
// See https://crbug.com/1174627.
class KeepAliveDevToolsTest : public InProcessBrowserTest {
 protected:
  void SetUpCommandLine(base::CommandLine* command_line) override {
    command_line->AppendSwitchASCII(switches::kRemoteDebuggingPort, "0");
    command_line->AppendSwitch(switches::kNoStartupWindow);
  }
};

IN_PROC_BROWSER_TEST_F(KeepAliveDevToolsTest, KeepsAliveUntilBrowserClose) {
  EXPECT_FALSE(browser_shutdown::IsTryingToQuit());
  EXPECT_TRUE(BrowserList::GetInstance()->empty());
  EXPECT_TRUE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
  EXPECT_TRUE(KeepAliveRegistry::GetInstance()->IsOriginRegistered(
      KeepAliveOrigin::REMOTE_DEBUGGING));
  chrome::NewEmptyWindow(ProfileManager::GetLastUsedProfile());
  EXPECT_FALSE(BrowserList::GetInstance()->empty());
  BrowserHandler handler(nullptr, std::string());
  handler.Close();
  ui_test_utils::WaitForBrowserToClose();
  EXPECT_FALSE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
  EXPECT_FALSE(KeepAliveRegistry::GetInstance()->IsOriginRegistered(
      KeepAliveOrigin::REMOTE_DEBUGGING));
}
#endif  // !BUILDFLAG(IS_CHROMEOS)

class DevToolsPolicyTest : public InProcessBrowserTest {
 protected:
  DevToolsPolicyTest() {
    provider_.SetDefaultReturns(
        /*is_initialization_complete_return=*/true,
        /*is_first_policy_load_complete_return=*/true);
  }

  void SetUpInProcessBrowserTestFixture() override {
    policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_);
  }
  testing::NiceMock<policy::MockConfigurationPolicyProvider> provider_;
};

IN_PROC_BROWSER_TEST_F(DevToolsPolicyTest, OpenBlockedDevTools) {
  base::Value::List blocklist;
  blocklist.Append("devtools://*");
  policy::PolicyMap policies;
  policies.Set(policy::key::kURLBlocklist, policy::POLICY_LEVEL_MANDATORY,
               policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
               base::Value(std::move(blocklist)), nullptr);
  provider_.UpdateChromePolicy(policies);

  WebContents* wc = browser()->tab_strip_model()->GetActiveWebContents();
  scoped_refptr<content::DevToolsAgentHost> agent(
      GetOrCreateDevToolsHostForWebContents(wc));
  DevToolsWindow::OpenDevToolsWindow(wc);
  DevToolsWindow* window = DevToolsWindow::FindDevToolsWindow(agent.get());
  if (window) {
    base::RunLoop run_loop;
    DevToolsWindowTesting::Get(window)->SetCloseCallback(
        run_loop.QuitClosure());
    run_loop.Run();
  }
  window = DevToolsWindow::FindDevToolsWindow(agent.get());
  ASSERT_EQ(nullptr, window);
}

class DevToolsExtensionHostsPolicyTest : public DevToolsExtensionTest {
 protected:
  DevToolsExtensionHostsPolicyTest() {
    provider_.SetDefaultReturns(
        /*is_initialization_complete_return=*/true,
        /*is_first_policy_load_complete_return=*/true);
    policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_);
  }
  void SetUpInProcessBrowserTestFixture() override {
    DevToolsExtensionTest::SetUpInProcessBrowserTestFixture();

    base::Value::Dict settings;
    settings.Set(
        "*", base::Value::Dict()
                 .Set(extensions::schema_constants::kPolicyBlockedHosts,
                      base::Value::List().Append("*://*.example.com"))
                 .Set(extensions::schema_constants::kPolicyAllowedHosts,
                      base::Value::List().Append("*://public.example.com")));

    policy::PolicyMap policies;
    policies.Set(policy::key::kExtensionSettings,
                 policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
                 policy::POLICY_SOURCE_CLOUD, base::Value(std::move(settings)),
                 nullptr);
    provider_.UpdateChromePolicy(policies);
  }

  void Run(const std::string& test_page, bool expect_success) {
    extensions::TestExtensionDir dir;

    dir.WriteManifest(
        BuildExtensionManifest("Runtime Hosts Policy", "devtools.html"));
    dir.WriteFile(
        FILE_PATH_LITERAL("devtools.html"),
        "<html><head><script src='devtools.js'></script></head></html>");
    dir.WriteFile(FILE_PATH_LITERAL("devtools.js"),
                  base::StringPrintf(R"(
        chrome.devtools.network.getHAR((result) => {
          setInterval(() => {
            top.postMessage(
              {testOutput: ('isError' in result !== %d) ? 'PASS' : 'FAIL'},
              '*'
            );
          }, 10);
        });)",
                                     expect_success));

    const Extension* extension = LoadExtensionFromPath(dir.UnpackedPath());
    ASSERT_TRUE(extension);
    RunTest("waitForTestResultsAsMessage", test_page);
  }

  testing::NiceMock<policy::MockConfigurationPolicyProvider> provider_;
  base::test::ScopedFeatureList scoped_feature_list_;
};

IN_PROC_BROWSER_TEST_F(DevToolsExtensionHostsPolicyTest,
                       CantInspectBlockedHost) {
  GURL url(embedded_test_server()->GetURL("example.com", kArbitraryPage));
  Run(url.spec(), /*expect_success*/ false);
}
IN_PROC_BROWSER_TEST_F(DevToolsExtensionHostsPolicyTest,
                       CantInspectBlockedSubdomainHost) {
  GURL url(embedded_test_server()->GetURL("foo.example.com", kArbitraryPage));
  Run(url.spec(), /*expect_success*/ false);
}
IN_PROC_BROWSER_TEST_F(DevToolsExtensionHostsPolicyTest,
                       CanInspectAllowedHttpHost) {
  GURL url(
      embedded_test_server()->GetURL("public.example.com", kArbitraryPage));
  Run(url.spec(), /*expect_success*/ true);
}

// Times out. See https://crbug.com/819285.
IN_PROC_BROWSER_TEST_F(SitePerProcessDevToolsTest,
                       DISABLED_InputDispatchEventsToOOPIF) {
  GURL url(
      embedded_test_server()->GetURL("a.com", "/devtools/oopif-input.html"));
  GURL iframe_url(embedded_test_server()->GetURL(
      "b.com", "/devtools/oopif-input-frame.html"));

  WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();

  content::TestNavigationManager navigation_manager(tab, url);
  content::TestNavigationManager navigation_manager_iframe(tab, iframe_url);

  tab->GetController().LoadURL(url, content::Referrer(),
                               ui::PAGE_TRANSITION_LINK, std::string());

  ASSERT_TRUE(navigation_manager.WaitForNavigationFinished());
  ASSERT_TRUE(navigation_manager_iframe.WaitForNavigationFinished());
  EXPECT_TRUE(content::WaitForLoadStop(tab));

  for (auto* frame : CollectAllRenderFrameHosts(GetInspectedTab())) {
    content::WaitForHitTestData(frame);
  }
  DevToolsWindow* window =
      DevToolsWindowTesting::OpenDevToolsWindowSync(GetInspectedTab(), false);
  RunTestFunction(window, "testInputDispatchEventsToOOPIF");
  DevToolsWindowTesting::CloseDevToolsWindowSync(window);
}

// See https://crbug.com/971241
IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest,
                       DISABLED_ExtensionWebSocketUserAgentOverride) {
  net::SpawnedTestServer websocket_server(
      net::SpawnedTestServer::TYPE_WS,
      base::FilePath(FILE_PATH_LITERAL("net/data/websocket")));
  websocket_server.set_websocket_basic_auth(false);
  ASSERT_TRUE(websocket_server.Start());
  uint16_t websocket_port = websocket_server.host_port_pair().port();

  LoadExtension("web_request");
  OpenDevToolsWindow(kEmptyTestPage, /* is_docked */ false);
  DispatchOnTestSuite(window_, "testExtensionWebSocketUserAgentOverride",
                      std::to_string(websocket_port).c_str());
  CloseDevToolsWindow();
}

IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest, SourceMapsFromExtension) {
  const Extension* extension =
      LoadExtensionForTest("Non-DevTools Extension", "" /* devtools_page */,
                           "" /* panel_iframe_src */);
  ASSERT_TRUE(extension);
  OpenDevToolsWindow(kEmptyTestPage, /* is_docked */ false);
  DispatchOnTestSuite(window_, "testSourceMapsFromExtension",
                      extension->id().c_str());
  CloseDevToolsWindow();
}

IN_PROC_BROWSER_TEST_F(DevToolsTest, SourceMapsFromDevtools) {
  OpenDevToolsWindow(kEmptyTestPage, /* is_docked */ false);
  DispatchOnTestSuite(window_, "testSourceMapsFromDevtools");
  CloseDevToolsWindow();
}

IN_PROC_BROWSER_TEST_F(DevToolsTest,
                       DoesNotCrashOnSourceMapsFromUnknownScheme) {
  OpenDevToolsWindow(kEmptyTestPage, /* is_docked */ false);
  DispatchOnTestSuite(window_, "testDoesNotCrashOnSourceMapsFromUnknownScheme");
  CloseDevToolsWindow();
}

IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest,
                       ExtensionWebSocketOfflineNetworkConditions) {
  net::SpawnedTestServer websocket_server(
      net::SpawnedTestServer::TYPE_WS,
      base::FilePath(FILE_PATH_LITERAL("net/data/websocket")));
  websocket_server.set_websocket_basic_auth(false);
  ASSERT_TRUE(websocket_server.Start());
  uint16_t websocket_port = websocket_server.host_port_pair().port();

  LoadExtension("web_request");
  OpenDevToolsWindow(kEmptyTestPage, /* is_docked */ false);
  DispatchOnTestSuite(window_, "testExtensionWebSocketOfflineNetworkConditions",
                      base::NumberToString(websocket_port).c_str());
  CloseDevToolsWindow();
}

IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest, IsDeveloperModeTrueHistogram) {
  browser()->profile()->GetPrefs()->SetBoolean(
      prefs::kExtensionsUIDeveloperMode, true);
  base::HistogramTester histograms;
  const char* histogram_name = "Extensions.DevTools.UserIsInDeveloperMode";

  LoadExtension("devtools_extension");
  RunTest("waitForTestResultsInConsole", kArbitraryPage);

  histograms.ExpectBucketCount(histogram_name, true, 2);
}

IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest, IsDeveloperModeFalseHistogram) {
  browser()->profile()->GetPrefs()->SetBoolean(
      prefs::kExtensionsUIDeveloperMode, false);
  base::HistogramTester histograms;
  const char* histogram_name = "Extensions.DevTools.UserIsInDeveloperMode";

  LoadExtension("devtools_extension");
  RunTest("waitForTestResultsInConsole", kArbitraryPage);

  histograms.ExpectBucketCount(histogram_name, false, 2);
}

namespace {

class DevToolsLocalizationTest : public DevToolsTest {
 public:
  bool NavigatorLanguageMatches(const std::string& expected_locale) {
    return content::EvalJs(main_web_contents(),
                           "window.navigator.language === "
                           "'" +
                               expected_locale + "'")
        .ExtractBool();
  }
};

}  // namespace

IN_PROC_BROWSER_TEST_F(DevToolsLocalizationTest,
                       NavigatorLanguageMatchesApplicationLocaleDocked) {
  g_browser_process->SetApplicationLocale("es");

  OpenDevToolsWindow("about:blank", /* is_docked */ true);
  EXPECT_TRUE(NavigatorLanguageMatches("es"));
  CloseDevToolsWindow();
}

IN_PROC_BROWSER_TEST_F(DevToolsLocalizationTest,
                       NavigatorLanguageMatchesApplicationLocaleUndocked) {
  g_browser_process->SetApplicationLocale("es");

  OpenDevToolsWindow("about:blank", /* is_docked */ false);
  EXPECT_TRUE(NavigatorLanguageMatches("es"));
  CloseDevToolsWindow();
}

IN_PROC_BROWSER_TEST_F(DevToolsLocalizationTest,
                       AcceptedLanguageChangesWhileDevToolsIsOpen) {
  g_browser_process->SetApplicationLocale("es");

  OpenDevToolsWindow("about:blank", true);
  EXPECT_TRUE(NavigatorLanguageMatches("es"));

  PrefService* prefs = browser()->profile()->GetPrefs();
  prefs->SetString(language::prefs::kAcceptLanguages, "de-DE");

  EXPECT_TRUE(NavigatorLanguageMatches("es"));

  CloseDevToolsWindow();
}

namespace {

class DevToolsFetchTest : public DevToolsTest {
 protected:
  content::EvalJsResult Fetch(
      const content::ToRenderFrameHost& execution_target,
      const std::string& url) {
    return content::EvalJs(execution_target, content::JsReplace(R"(
      (async function() {
        const response = await fetch($1);
        return response.status;
      })();
    )",
                                                                url));
  }

  content::EvalJsResult FetchFromDevToolsWindow(const std::string& url) {
    WebContents* wc = DevToolsWindowTesting::Get(window_)->main_web_contents();
    return Fetch(wc, url);
  }
};

}  // namespace

IN_PROC_BROWSER_TEST_F(DevToolsFetchTest,
                       DevToolsFetchFromDevToolsSchemeUndocked) {
  OpenDevToolsWindow("about:blank", false);

  EXPECT_EQ(200, FetchFromDevToolsWindow(
                     "devtools://devtools/bundled/devtools_compatibility.js"));

  CloseDevToolsWindow();
}

IN_PROC_BROWSER_TEST_F(DevToolsFetchTest,
                       DevToolsFetchFromDevToolsSchemeDocked) {
  OpenDevToolsWindow("about:blank", true);

  EXPECT_EQ(200, FetchFromDevToolsWindow(
                     "devtools://devtools/bundled/devtools_compatibility.js"));

  CloseDevToolsWindow();
}

IN_PROC_BROWSER_TEST_F(DevToolsFetchTest, DevToolsFetchFromHttpDisallowed) {
  OpenDevToolsWindow("about:blank", true);

  const auto result = FetchFromDevToolsWindow("http://www.google.com");
  EXPECT_THAT(result.error,
              ::testing::StartsWith(
                  "a JavaScript error: \"TypeError: Failed to fetch\n"));

  CloseDevToolsWindow();
}

IN_PROC_BROWSER_TEST_F(DevToolsFetchTest, FetchFromDevToolsSchemeIsProhibited) {
  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL("about:blank")));

  const auto result =
      Fetch(GetInspectedTab(),
            "devtools://devtools/bundled/devtools_compatibility.js");
  EXPECT_THAT(result.error,
              ::testing::StartsWith(
                  "a JavaScript error: \"TypeError: Failed to fetch\n"));
}

IN_PROC_BROWSER_TEST_F(DevToolsTest, HostBindingsSyncIntegration) {
  // Smoke test to make sure that `registerPreference` works from JavaScript.
  OpenDevToolsWindow("about:blank", true);
  LoadLegacyFilesInFrontend(window_);

  WebContents* wc = DevToolsWindowTesting::Get(window_)->main_web_contents();
  ASSERT_TRUE(content::ExecJs(
      wc, content::JsReplace(
              R"(
    Host.InspectorFrontendHost.setPreference($1, 'false');  // Disable sync.
    Host.InspectorFrontendHost.registerPreference(
        'synced_setting', {synced: true});
    Host.InspectorFrontendHost.registerPreference(
        'unsynced_setting', {synced: false});
    Host.InspectorFrontendHost.setPreference('synced_setting', 'synced value');
    Host.InspectorFrontendHost.setPreference(
        'unsynced_setting', 'unsynced value');
  )",
              DevToolsSettings::kSyncDevToolsPreferencesFrontendName)));

  const base::Value::Dict& synced_settings =
      browser()->profile()->GetPrefs()->GetDict(
          prefs::kDevToolsSyncedPreferencesSyncDisabled);
  const base::Value::Dict& unsynced_settings =
      browser()->profile()->GetPrefs()->GetDict(prefs::kDevToolsPreferences);
  EXPECT_EQ(*synced_settings.FindString("synced_setting"), "synced value");
  EXPECT_EQ(*unsynced_settings.FindString("unsynced_setting"),
            "unsynced value");
}

IN_PROC_BROWSER_TEST_F(DevToolsTest, NoJavascriptUrlOnDevtools) {
  // As per crbug/1115460 one could use javascript: url as a homepage URL and
  // then trigger homepage navigation (e.g. via keyboard shortcut) to execute in
  // the context of the privileged devtools frontend.
  OpenDevToolsWindow("about:blank", true);

  WebContents* wc = DevToolsWindowTesting::Get(window_)->main_web_contents();
  wc->GetController().LoadURL(GURL("javascript:window.xss=true"),
                              content::Referrer(), ui::PAGE_TRANSITION_TYPED,
                              std::string());
  EXPECT_EQ(false, content::EvalJs(wc, "!!window.xss"));
}

class DevToolsSyncTest : public SyncTest {
 public:
  DevToolsSyncTest() : SyncTest(SyncTest::SINGLE_CLIENT) {}
};

IN_PROC_BROWSER_TEST_F(DevToolsSyncTest, GetSyncInformation) {
  // Smoke test to make sure that `getSyncInformation` works from JavaScript.
  ASSERT_TRUE(SetupSync());
  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL("about:blank")));

  DevToolsWindow* window = DevToolsWindowTesting::OpenDevToolsWindowSync(
      browser()->tab_strip_model()->GetActiveWebContents(), GetProfile(0),
      true);
  LoadLegacyFilesInFrontend(window);

  WebContents* wc = DevToolsWindowTesting::Get(window)->main_web_contents();
  const auto result = content::EvalJs(wc, content::JsReplace(R"(
      (async function() {
        return new Promise(resolve => {
          Host.InspectorFrontendHost.getSyncInformation(resolve);
        });
      })();
    )"));
  ASSERT_TRUE(result.value.is_dict());
  EXPECT_TRUE(*result.value.GetDict().FindBool("isSyncActive"));
  EXPECT_TRUE(*result.value.GetDict().FindBool("arePreferencesSynced"));
  EXPECT_EQ(*result.value.GetDict().FindString("accountEmail"),
            "user@gmail.com");
}

// Regression test for https://crbug.com/1270184.
// TODO(https://crbug.com/1277018): Fix flakyness. Test is disabled for now.
IN_PROC_BROWSER_TEST_F(DevToolsTest, DISABLED_NoCrashFor1270184) {
  OpenDevToolsWindow("/devtools/regress-crbug-1270184.html", true);
}

class DevToolsProcessPerSiteUpToMainFrameThresholdTest : public DevToolsTest {
 public:
  DevToolsProcessPerSiteUpToMainFrameThresholdTest() {
    scoped_feature_list_.InitAndEnableFeature(
        features::kProcessPerSiteUpToMainFrameThreshold);
  }

  ~DevToolsProcessPerSiteUpToMainFrameThresholdTest() override = default;

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

IN_PROC_BROWSER_TEST_F(DevToolsProcessPerSiteUpToMainFrameThresholdTest,
                       DontReuseProcess) {
  OpenDevToolsWindow(kDebuggerTestPage, false);
  DevToolsWindow* window =
      DevToolsWindowTesting::OpenDevToolsWindowSync(main_web_contents(), true);
  WebContents* webcontents =
      DevToolsWindowTesting::Get(window)->main_web_contents();

  DevToolsWindow* window2 =
      DevToolsWindowTesting::OpenDevToolsWindowSync(GetInspectedTab(), false);
  WebContents* webcontents2 =
      DevToolsWindowTesting::Get(window2)->main_web_contents();

  ASSERT_NE(webcontents->GetPrimaryMainFrame()->GetProcess(),
            webcontents2->GetPrimaryMainFrame()->GetProcess());
}
