chromium/chrome/browser/webauthn/chrome_webauthn_autofill_interactive_uitest.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 <memory>
#include <string>
#include <vector>

#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "crypto/scoped_fake_user_verifying_key_provider.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_logging_settings.h"
#include "build/build_config.h"
#include "chrome/browser/password_manager/profile_password_store_factory.h"
#include "chrome/browser/signin/identity_test_environment_profile_adaptor.h"
#include "chrome/browser/ssl/cert_verifier_browser_test.h"
#include "chrome/browser/sync/device_info_sync_service_factory.h"
#include "chrome/browser/sync/sync_service_factory.h"
#include "chrome/browser/ui/autofill/autofill_popup_controller_impl.h"
#include "chrome/browser/ui/autofill/autofill_popup_controller_impl_test_api.h"
#include "chrome/browser/ui/autofill/autofill_suggestion_controller.h"
#include "chrome/browser/ui/autofill/chrome_autofill_client.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/webauthn/chrome_authenticator_request_delegate.h"
#include "chrome/browser/webauthn/passkey_model_factory.h"
#include "chrome/browser/webauthn/test_util.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/autofill/core/browser/ui/suggestion_hiding_reason.h"
#include "components/autofill/core/browser/ui/suggestion_type.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "components/network_session_configurator/common/network_switches.h"
#include "components/password_manager/core/browser/password_store/password_store_interface.h"
#include "components/strings/grit/components_strings.h"
#include "components/sync/base/features.h"
#include "components/sync/test/test_sync_service.h"
#include "components/sync_device_info/device_info.h"
#include "components/sync_device_info/fake_device_info_sync_service.h"
#include "components/sync_device_info/fake_device_info_tracker.h"
#include "components/trusted_vault/proto/vault.pb.h"
#include "components/trusted_vault/test/mock_trusted_vault_connection.h"
#include "components/trusted_vault/trusted_vault_connection.h"
#include "components/webauthn/core/browser/test_passkey_model.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/scoped_authenticator_environment_for_testing.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "crypto/scoped_mock_unexportable_key_provider.h"
#include "device/bluetooth/bluetooth_adapter_factory.h"
#include "device/bluetooth/test/mock_bluetooth_adapter.h"
#include "device/fido/cable/v2_handshake.h"
#include "device/fido/features.h"
#include "device/fido/fido_request_handler_base.h"
#include "device/fido/fido_transport_protocol.h"
#include "device/fido/virtual_ctap2_device.h"
#include "device/fido/virtual_fido_device_factory.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/l10n/l10n_util.h"
#include "url/gurl.h"

#if BUILDFLAG(IS_WIN)
#include "device/fido/win/fake_webauthn_api.h"
#include "device/fido/win/util.h"
#endif  // BUILDFLAG(IS_WIN)

#if BUILDFLAG(IS_MAC)
#include "device/fido/mac/util.h"
#endif  // BUILDFLAG(IS_MAC)

namespace {

static constexpr char kRpId[] =;
static constexpr uint8_t kCredentialID1[] =;
static constexpr uint8_t kCredentialID2[] =;
static constexpr char16_t kPhoneName[] =;

static constexpr char kConditionalUIRequest[] =;

static constexpr char kConditionalUIRequestFiltered[] =;

sync_pb::WebauthnCredentialSpecifics CreatePasskey() {}

syncer::DeviceInfo CreateDeviceInfo() {}

std::u16string ExpectedPasskeyLabel() {}

// Autofill integration tests. This file contains end-to-end tests for
// integration between WebAuthn and Autofill. These tests are sensitive to focus
// changes, so they are interactive UI tests.

// Base class for autofill integration tests, contains the actual test code but
// no setup.
class WebAuthnAutofillIntegrationTest : public CertVerifierBrowserTest {};

// Autofill integration test using the devtools virtual environment.
class WebAuthnDevtoolsAutofillIntegrationTest
    : public WebAuthnAutofillIntegrationTest {};

IN_PROC_BROWSER_TEST_F(WebAuthnDevtoolsAutofillIntegrationTest, SelectAccount) {}

IN_PROC_BROWSER_TEST_F(WebAuthnDevtoolsAutofillIntegrationTest, Abort) {}

IN_PROC_BROWSER_TEST_F(WebAuthnDevtoolsAutofillIntegrationTest,
                       SelectAccountWithAllowCredentials) {}

IN_PROC_BROWSER_TEST_F(WebAuthnDevtoolsAutofillIntegrationTest,
                       SelectAccountWithAllowCredentialsFiltered) {}

IN_PROC_BROWSER_TEST_F(WebAuthnDevtoolsAutofillIntegrationTest,
                       GPMPasskeys) {}

// Tests that downloading passkeys from sync during a conditional UI also
// updates the autofill popup with the newly downloaded credentials.
IN_PROC_BROWSER_TEST_F(WebAuthnDevtoolsAutofillIntegrationTest,
                       GPMPasskeys_UpdatePasskeys) {}

#if BUILDFLAG(IS_WIN)
// Autofill integration test using the Windows fake API.
class WebAuthnWindowsAutofillIntegrationTest
    : public WebAuthnAutofillIntegrationTest {
 public:
  void SetUpOnMainThread() override {
    WebAuthnAutofillIntegrationTest::SetUpOnMainThread();

    // Set up the fake Windows platform authenticator.
    fake_webauthn_api_ = std::make_unique<device::FakeWinWebAuthnApi>();
    fake_webauthn_api_->set_version(WEBAUTHN_API_VERSION_4);
    fake_webauthn_api_->set_is_uvpaa(true);
    fake_webauthn_api_->set_supports_silent_discovery(true);
    device::PublicKeyCredentialUserEntity user({1, 2, 3, 4}, "flandre",
                                               "Flandre Scarlet");
    device::PublicKeyCredentialRpEntity rp(kRpId);
    fake_webauthn_api_->InjectDiscoverableCredential(
        kCredentialID1, std::move(rp), std::move(user));

    win_webauthn_api_override_ =
        std::make_unique<device::WinWebAuthnApi::ScopedOverride>(
            fake_webauthn_api_.get());
  }

  void PostRunTestOnMainThread() override {
    // To avoid dangling raw_ptr's, these objects need to be destroyed before
    // the test class.
    win_webauthn_api_override_.reset();
    WebAuthnAutofillIntegrationTest::PostRunTestOnMainThread();
  }

  std::u16string GetDeviceString() override {
    return l10n_util::GetStringUTF16(
        IDS_PASSWORD_MANAGER_PASSKEY_FROM_WINDOWS_HELLO);
  }

 protected:
  std::unique_ptr<device::FakeWinWebAuthnApi> fake_webauthn_api_;
  std::unique_ptr<device::WinWebAuthnApi::ScopedOverride>
      win_webauthn_api_override_;
};

IN_PROC_BROWSER_TEST_F(WebAuthnWindowsAutofillIntegrationTest, SelectAccount) {
  RunSelectAccountTest(kConditionalUIRequest);
}

IN_PROC_BROWSER_TEST_F(WebAuthnWindowsAutofillIntegrationTest,
                       SelectAccountWithAllowCredentials) {
  RunSelectAccountTest(kConditionalUIRequestFiltered);
}

IN_PROC_BROWSER_TEST_F(WebAuthnWindowsAutofillIntegrationTest,
                       SelectAccountWithAllowCredentialsFiltered) {
  device::PublicKeyCredentialUserEntity user({6, 7, 8, 9}, "sakuya",
                                             "Sakuya Izayoi");
  device::PublicKeyCredentialRpEntity rp(kRpId);
  fake_webauthn_api_->InjectDiscoverableCredential(
      kCredentialID2, std::move(rp), std::move(user));
  RunSelectAccountTest(kConditionalUIRequestFiltered);
}

IN_PROC_BROWSER_TEST_F(WebAuthnWindowsAutofillIntegrationTest, Abort) {
  RunAbortTest();
}
#endif  // BUILDFLAG(IS_WIN)

}  // namespace