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

// Copyright 2023 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_lock_screen_browser_test_base.h"

#include <string>

#include "ash/auth/active_session_auth_controller_impl.h"
#include "ash/constants/ash_features.h"
#include "ash/public/cpp/in_session_auth_dialog_controller.h"
#include "ash/shell.h"
#include "base/check_op.h"
#include "base/test/test_future.h"
#include "chrome/browser/ash/login/test/logged_in_user_mixin.h"
#include "chrome/browser/ash/login/test/user_auth_config.h"
#include "chrome/test/base/mixin_based_in_process_browser_test.h"
#include "chrome/test/data/webui/chromeos/settings/test_api.test-mojom-test-utils.h"
#include "chromeos/ash/components/osauth/impl/auth_surface_registry.h"
#include "chromeos/ash/components/osauth/public/auth_engine_api.h"
#include "chromeos/ash/components/osauth/public/auth_parts.h"
#include "chromeos/ash/components/osauth/public/common_types.h"

namespace ash::settings {

OSSettingsLockScreenBrowserTestBase::OSSettingsLockScreenBrowserTestBase(
    ash::AshAuthFactor password_type) {
  // We configure FakeUserDataAuthClient (via `cryptohome_`) here and not
  // later because the global PinBackend object reads whether or not
  // cryptohome PINs are supported on startup. If we set up
  // FakeUserDataAuthClient in SetUpOnMainThread, then PinBackend would
  // determine whether PINs are supported before we have configured
  // FakeUserDataAuthClient.
  test::UserAuthConfig config;
  if (password_type == ash::AshAuthFactor::kGaiaPassword) {
    config.WithOnlinePassword(kPassword);
  } else {
    CHECK_EQ(password_type, ash::AshAuthFactor::kLocalPassword);
    config.WithLocalPassword(kPassword);
  }

  logged_in_user_mixin_ = std::make_unique<LoggedInUserMixin>(
      &mixin_host_, /*test_base=*/this, embedded_test_server(),
      LoggedInUserMixin::LogInType::kConsumer,
      /*include_initial_user=*/true,
      /*account_id=*/std::nullopt, config);
  cryptohome_ = &logged_in_user_mixin_->GetCryptohomeMixin();
  cryptohome_->set_enable_auth_check(true);
  cryptohome_->set_supports_low_entropy_credentials(true);
  cryptohome_->MarkUserAsExisting(GetAccountId());
}

OSSettingsLockScreenBrowserTestBase::~OSSettingsLockScreenBrowserTestBase() =
    default;

void OSSettingsLockScreenBrowserTestBase::SetUpOnMainThread() {
  MixinBasedInProcessBrowserTest::SetUpOnMainThread();
  logged_in_user_mixin_->LogInUser();
}

mojom::LockScreenSettingsAsyncWaiter
OSSettingsLockScreenBrowserTestBase::OpenLockScreenSettings() {
  if (ash::features::IsUseAuthPanelInSessionEnabled()) {
    base::test::TestFuture<AuthSurfaceRegistry::AuthSurface> future;
    auto subscription =
        ash::AuthParts::Get()->GetAuthSurfaceRegistry()->RegisterShownCallback(
            future.GetCallback());

    auto os_settings_driver = OpenOSSettings();

    lock_screen_settings_remote_ =
        mojo::Remote(os_settings_driver.GoToLockScreenSettings());

    auto surface = future.Get();
    CHECK_EQ(surface, AuthSurfaceRegistry::AuthSurface::kInSession);

    base::RunLoop().RunUntilIdle();
  } else {
    auto os_settings_driver = OpenOSSettings();
    lock_screen_settings_remote_ =
        mojo::Remote(os_settings_driver.GoToLockScreenSettings());
  }

  return mojom::LockScreenSettingsAsyncWaiter(
      lock_screen_settings_remote_.get());
}

void OSSettingsLockScreenBrowserTestBase::AuthenticateUsingPassword() {
  auto* controller = static_cast<ActiveSessionAuthControllerImpl*>(
      Shell::Get()->active_session_auth_controller());

  ActiveSessionAuthControllerImpl::TestApi(controller)
      .SubmitPassword(kPassword);

  base::RunLoop().RunUntilIdle();
}

mojom::LockScreenSettingsAsyncWaiter
OSSettingsLockScreenBrowserTestBase::OpenLockScreenSettingsAndAuthenticate() {
  if (ash::features::IsUseAuthPanelInSessionEnabled()) {
    OpenLockScreenSettings();
    AuthenticateUsingPassword();
  } else {
    OpenLockScreenSettings().Authenticate(kPassword);
  }

  // The mojom AsyncWaiter classes have deleted copy constructors even though
  // they only hold a non-owning pointer to a mojo remote. This restriction
  // should probably be dropped, so that we can just return the async waiter
  // created by the call to `OpenLockScreenSettings` here. As a workaround, we
  // simply create a new waiter.
  return mojom::LockScreenSettingsAsyncWaiter{
      lock_screen_settings_remote_.get()};
}

mojom::LockScreenSettingsAsyncWaiter OSSettingsLockScreenBrowserTestBase::
    OpenLockScreenSettingsDeepLinkAndAuthenticate(
        const std::string& setting_id) {
  std::string relative_url = "/osPrivacy/lockScreen?settingId=";
  relative_url += setting_id;
  if (ash::features::IsUseAuthPanelInSessionEnabled()) {
    base::test::TestFuture<AuthSurfaceRegistry::AuthSurface> future;
    auto subscription =
        ash::AuthParts::Get()->GetAuthSurfaceRegistry()->RegisterShownCallback(
            future.GetCallback());

    auto os_settings_driver = OpenOSSettings(relative_url);

    auto surface = future.Get();
    CHECK_EQ(surface, AuthSurfaceRegistry::AuthSurface::kInSession);

    base::RunLoop().RunUntilIdle();

    AuthenticateUsingPassword();

    lock_screen_settings_remote_ =
        mojo::Remote(os_settings_driver.AssertOnLockScreenSettings());
  } else {
    auto os_settings_driver = OpenOSSettings(relative_url);
    lock_screen_settings_remote_ =
        mojo::Remote(os_settings_driver.AssertOnLockScreenSettings());
    mojom::LockScreenSettingsAsyncWaiter(lock_screen_settings_remote_.get())
        .Authenticate(kPassword);
  }

  return mojom::LockScreenSettingsAsyncWaiter(
      lock_screen_settings_remote_.get());
}

const AccountId& OSSettingsLockScreenBrowserTestBase::GetAccountId() {
  return logged_in_user_mixin_->GetAccountId();
}

mojom::OSSettingsDriverAsyncWaiter
OSSettingsLockScreenBrowserTestBase::OpenOSSettings(
    const std::string& relative_url) {
  os_settings_driver_remote_ =
      mojo::Remote(os_settings_mixin_.OpenOSSettings(relative_url));
  return mojom::OSSettingsDriverAsyncWaiter(os_settings_driver_remote_.get());
}

}  // namespace ash::settings