chromium/chrome/browser/ui/webui/ash/settings/test_support/os_settings_browser_test_mixin.cc

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

#include "chrome/browser/ui/webui/ash/settings/test_support/os_settings_browser_test_mixin.h"

#include <memory>
#include <optional>
#include <string>
#include <utility>

#include "base/path_service.h"
#include "base/test/scoped_run_loop_timeout.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/webui/ash/settings/os_settings_ui.h"
#include "chrome/test/base/web_ui_test_data_source.h"
#include "chrome/test/data/webui/chromeos/settings/test_api.test-mojom-test-utils.h"
#include "chrome/test/data/webui/chromeos/settings/test_api.test-mojom.h"
#include "content/public/browser/web_ui_data_source.h"
#include "content/public/test/browser_test_utils.h"
#include "ui/base/resource/resource_bundle.h"

namespace ash::settings {

OSSettingsBrowserTestMixin::BrowserProcessServer::BrowserProcessServer() =
    default;

OSSettingsBrowserTestMixin::BrowserProcessServer::~BrowserProcessServer() =
    default;

void OSSettingsBrowserTestMixin::BrowserProcessServer::RegisterOSSettingsDriver(
    mojo::PendingRemote<mojom::OSSettingsDriver> driver,
    base::OnceCallback<void()> cont) {
  CHECK(!os_settings_driver_.has_value());
  os_settings_driver_ = mojo::Remote(std::move(driver));
  CHECK(os_settings_driver_.value().get())
      << "OSSettingsDriver remote is invalid";
  std::move(cont).Run();
}

mojo::Remote<mojom::OSSettingsDriver>
OSSettingsBrowserTestMixin::BrowserProcessServer::ReleaseOSSettingsDriver() {
  CHECK(os_settings_driver_.has_value())
      << "OSSettingsDriver implementation is not registered";
  CHECK(os_settings_driver_.value().get());

  auto result = std::move(*os_settings_driver_);
  os_settings_driver_ = std::nullopt;
  return result;
}

void OSSettingsBrowserTestMixin::BrowserProcessServer::Bind(
    content::RenderFrameHost* render_frame_host,
    mojo::PendingReceiver<mojom::OSSettingsBrowserProcess> receiver) {
  receivers_.Add(this, std::move(receiver));
}

OSSettingsBrowserTestMixin::OSSettingsUIProvider::OSSettingsUIProvider() =
    default;

OSSettingsBrowserTestMixin::OSSettingsUIProvider::~OSSettingsUIProvider() =
    default;

std::unique_ptr<content::WebUIController>
OSSettingsBrowserTestMixin::OSSettingsUIProvider::NewWebUI(
    content::WebUI* web_ui,
    const GURL& url) {
  auto controller = std::make_unique<OSSettingsUI>(web_ui);
  webui::CreateAndAddWebUITestDataSource(
      web_ui->GetWebContents()->GetBrowserContext());
  return controller;
}

OSSettingsBrowserTestMixin::TestBrowserClient::TestBrowserClient(
    BrowserProcessServer* server)
    : browser_process_server_(server) {
  CHECK(browser_process_server_);
}
OSSettingsBrowserTestMixin::TestBrowserClient::~TestBrowserClient() = default;

void OSSettingsBrowserTestMixin::TestBrowserClient::
    RegisterBrowserInterfaceBindersForFrame(
        content::RenderFrameHost* render_frame_host,
        mojo::BinderMapWithContext<content::RenderFrameHost*>* map) {
  ChromeContentBrowserClient::RegisterBrowserInterfaceBindersForFrame(
      render_frame_host, map);

  map->Add<mojom::OSSettingsBrowserProcess>(
      base::BindRepeating(&BrowserProcessServer::Bind,
                          base::Unretained(browser_process_server_.get())));
}

OSSettingsBrowserTestMixin::OSSettingsBrowserTestMixin(
    InProcessBrowserTestMixinHost* host)
    : InProcessBrowserTestMixin(host) {
  test_factory_.AddFactoryOverride("os-settings", &os_settings_ui_provider_);
}

OSSettingsBrowserTestMixin::~OSSettingsBrowserTestMixin() = default;

void OSSettingsBrowserTestMixin::SetUpOnMainThread() {
  // Override browser client to bind our BrowserTestApi implementation.
  content::SetBrowserClientForTesting(&test_browser_client_);

  // Load browser test resource bundle.
  base::FilePath pak_path;
  CHECK(base::PathService::Get(base::DIR_ASSETS, &pak_path));
  pak_path = pak_path.AppendASCII("browser_tests.pak");
  ui::ResourceBundle::GetSharedInstance().AddDataPackFromPath(
      pak_path, ui::kScaleFactorNone);
}

mojo::Remote<mojom::OSSettingsDriver>
OSSettingsBrowserTestMixin::OpenOSSettings(const std::string& relative_url) {
  // Open os-settings page.
  BrowserList* browser_list = BrowserList::GetInstance();
  CHECK(browser_list);
  Browser* browser = browser_list->GetLastActive();

  GURL test_url("chrome://os-settings" + relative_url);
  content::RenderFrameHost* render_frame_host =
      ui_test_utils::NavigateToURL(browser, test_url);

  // Load test_api.js to register the os settings driver mojo implementation.
  static const char* script = R"(
      (async function () {
         const {register} =
             await import('chrome://webui-test/chromeos/settings/test_api.js');
        await register();
        return true;
      })()
  )";
  CHECK_EQ(true, content::EvalJs(render_frame_host, script));

  return browser_process_server_.ReleaseOSSettingsDriver();
}

}  // namespace ash::settings