#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include <memory>
#include <sstream>
#include <vector>
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/rand_util.h"
#include "base/run_loop.h"
#include "base/task/sequenced_task_runner.h"
#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/values_test_util.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/install_verifier.h"
#include "chrome/browser/extensions/test_extension_system.h"
#include "chrome/browser/password_manager/chrome_webauthn_credentials_delegate.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ssl/cert_verifier_browser_test.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/passwords/passwords_model_delegate.h"
#include "chrome/browser/webauthn/authenticator_request_dialog_controller.h"
#include "chrome/browser/webauthn/authenticator_transport.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/keyed_service/content/browser_context_dependency_manager.h"
#include "components/network_session_configurator/common/network_switches.h"
#include "components/password_manager/core/common/password_manager_ui.h"
#include "components/sync/base/features.h"
#include "components/sync/protocol/webauthn_credential_specifics.pb.h"
#include "components/webauthn/core/browser/test_passkey_model.h"
#include "content/public/browser/authenticator_request_client_delegate.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/scoped_authenticator_environment_for_testing.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "device/bluetooth/bluetooth_adapter_factory.h"
#include "device/bluetooth/test/mock_bluetooth_adapter.h"
#include "device/fido/cable/cable_discovery_data.h"
#include "device/fido/discoverable_credential_metadata.h"
#include "device/fido/features.h"
#include "device/fido/fido_parsing_utils.h"
#include "device/fido/fido_request_handler_base.h"
#include "device/fido/fido_transport_protocol.h"
#include "device/fido/fido_types.h"
#include "device/fido/public_key_credential_user_entity.h"
#include "device/fido/virtual_ctap2_device.h"
#include "device/fido/virtual_fido_device.h"
#include "device/fido/virtual_fido_device_factory.h"
#include "extensions/common/extension_builder.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "url/gurl.h"
#if BUILDFLAG(IS_WIN)
#include "device/fido/win/fake_webauthn_api.h"
#include "device/fido/win/webauthn_api.h"
#endif
namespace {
static constexpr uint8_t kCredentialID[] = …;
static constexpr uint8_t kCredentialID2[] = …;
constexpr uint8_t kUserId1[] = …;
constexpr uint8_t kUserId2[] = …;
constexpr char kUsername1[] = …;
constexpr char kDisplayName1[] = …;
constexpr char kUsername2[] = …;
constexpr char kDisplayName2[] = …;
sync_pb::WebauthnCredentialSpecifics CreateWebAuthnCredentialSpecifics(
base::span<const uint8_t> credential_id,
base::span<const uint8_t> user_id,
const char* username,
const char* display_name) { … }
class WebAuthnBrowserTest : public CertVerifierBrowserTest { … };
static constexpr char kGetAssertionCredID1234[] = …;
static constexpr char kMakeCredential[] = …;
static constexpr char kMakeDiscoverableCredential[] = …;
IN_PROC_BROWSER_TEST_F(WebAuthnBrowserTest, ChromeExtensions) { … }
#if BUILDFLAG(IS_WIN)
IN_PROC_BROWSER_TEST_F(WebAuthnBrowserTest, WinLargeBlob) {
ASSERT_TRUE(ui_test_utils::NavigateToURL(
browser(), https_server_.GetURL("www.example.com", "/title1.html")));
device::FakeWinWebAuthnApi fake_api;
fake_api.set_version(WEBAUTHN_API_VERSION_3);
device::WinWebAuthnApi::ScopedOverride win_webauthn_api_override(&fake_api);
auto virtual_device_factory =
std::make_unique<device::test::VirtualFidoDeviceFactory>();
virtual_device_factory->set_discover_win_webauthn_api_authenticator(true);
content::ScopedAuthenticatorEnvironmentForTesting auth_env(
std::move(virtual_device_factory));
constexpr char kMakeCredentialLargeBlob[] = R"(
let cred_id;
const blob = "blobby volley";
navigator.credentials.create({ publicKey: {
challenge: new TextEncoder().encode('climb a mountain'),
rp: { name: 'Acme' },
user: {
id: new TextEncoder().encode('1098237235409872'),
name: '[email protected]',
displayName: 'Avery A. Jones'},
pubKeyCredParams: [{ type: 'public-key', alg: '-257'}],
authenticatorSelection: {
requireResidentKey: true,
},
extensions: { largeBlob: { support: 'required' } },
}}).then(cred => {
cred_id = cred.rawId;
if (!cred.getClientExtensionResults().largeBlob ||
!cred.getClientExtensionResults().largeBlob.supported) {
throw new Error('large blob not supported');
}
return navigator.credentials.get({ publicKey: {
challenge: new TextEncoder().encode('run a marathon'),
allowCredentials: [{type: 'public-key', id: cred_id}],
extensions: {
largeBlob: {
write: new TextEncoder().encode(blob),
},
},
}});
}).then(assertion => {
if (!assertion.getClientExtensionResults().largeBlob.written) {
throw new Error('large blob not written to');
}
return navigator.credentials.get({ publicKey: {
challenge: new TextEncoder().encode('solve p=np'),
allowCredentials: [{type: 'public-key', id: cred_id}],
extensions: {
largeBlob: {
read: true,
},
},
}});
}).then(assertion => {
if (new TextDecoder().decode(
assertion.getClientExtensionResults().largeBlob.blob) != blob) {
throw new Error('blob does not match');
}
return 'webauthn: OK';
}).catch(error => 'webauthn: ' + error.toString());)";
EXPECT_EQ(
"webauthn: OK",
content::EvalJs(browser()->tab_strip_model()->GetActiveWebContents(),
kMakeCredentialLargeBlob));
}
#endif
class WebAuthnGpmPasskeyTest : public WebAuthnBrowserTest { … };
IN_PROC_BROWSER_TEST_F(WebAuthnGpmPasskeyTest, FilterGPMPasskeys) { … }
IN_PROC_BROWSER_TEST_F(WebAuthnGpmPasskeyTest,
SignalUnknownCredentialGPMPasskeys) { … }
IN_PROC_BROWSER_TEST_F(WebAuthnGpmPasskeyTest,
SignalAllAcceptedCredsNoPasskeyDeletion) { … }
IN_PROC_BROWSER_TEST_F(WebAuthnGpmPasskeyTest,
SignalAllAcceptedCredsPasskeyDeletion) { … }
IN_PROC_BROWSER_TEST_F(WebAuthnGpmPasskeyTest, ReportInvalidStrings) { … }
IN_PROC_BROWSER_TEST_F(WebAuthnGpmPasskeyTest,
SignalCurrentUserDetailsGPMPasskeys) { … }
IN_PROC_BROWSER_TEST_F(WebAuthnGpmPasskeyTest,
ReportCurrentUserDetailsWithNoChanges) { … }
class WebAuthnHintsTest : public WebAuthnBrowserTest { … };
static constexpr char kMakeCredentialWithHints[] = …;
IN_PROC_BROWSER_TEST_F(WebAuthnHintsTest, HintsArePassedThrough) { … }
class WebAuthnConditionalUITest : public WebAuthnBrowserTest { … };
static constexpr char kConditionalUIRequest[] = …;
IN_PROC_BROWSER_TEST_F(WebAuthnConditionalUITest,
ConditionalUIOtherDeviceButton) { … }
class WebAuthnCableExtension : public WebAuthnBrowserTest { … };
IN_PROC_BROWSER_TEST_F(WebAuthnCableExtension, ServerLink) { … }
class WebAuthnCableSecondFactor : public WebAuthnBrowserTest { … };
#if BUILDFLAG(IS_MAC)
#define MAYBE_Test …
#else
#define MAYBE_Test …
#endif
IN_PROC_BROWSER_TEST_F(WebAuthnCableSecondFactor, MAYBE_Test) { … }
IN_PROC_BROWSER_TEST_F(WebAuthnCableSecondFactor, RequestTypesMakeCredential) { … }
IN_PROC_BROWSER_TEST_F(WebAuthnCableSecondFactor,
RequestTypesMakeDiscoverableCredential) { … }
}