Commit e122308b authored by Martin Kreichgauer's avatar Martin Kreichgauer Committed by Commit Bot

fido: populate TransportAvailabilityInfo.has_recognized_mac_touch_id_credential

This introduces PlatformAuthenticatorInfo as a parameter object to
FidoRequestHandlerBase::SetPlatformAuthenticatorOrMarkUnavailable. The
struct holds the existing std::unique_ptr<FidoAuthenticator>, which is
the platform authenticator itself, and an additional bool indicating
whether the authenticator has a matching credential for
GetAssertionRequest. The bool is plumbed through to
TransportAvailabilityInfo for consideration by the UI.

Bug: 847985
Change-Id: Ice46685eef31eb29cb8fdcb0d471e4b40bfb97b3
Reviewed-on: https://chromium-review.googlesource.com/1179088
Commit-Queue: Martin Kreichgauer <martinkr@google.com>
Reviewed-by: default avatarBalazs Engedy <engedy@chromium.org>
Reviewed-by: default avatarJun Choi <hongjunchoi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#584580}
parent ae5bd514
...@@ -568,11 +568,14 @@ void AuthenticatorImpl::GetAssertion( ...@@ -568,11 +568,14 @@ void AuthenticatorImpl::GetAssertion(
client_data_json_ = SerializeCollectedClientDataToJson( client_data_json_ = SerializeCollectedClientDataToJson(
client_data::kGetType, caller_origin, std::move(options->challenge)); client_data::kGetType, caller_origin, std::move(options->challenge));
auto ctap_request = CreateCtapGetAssertionRequest(
ConstructClientDataHash(client_data_json_), std::move(options),
alternative_application_parameter_);
auto opt_platform_authenticator_info =
CreatePlatformAuthenticatorIfAvailableAndCheckIfCredentialExists(
ctap_request);
request_ = std::make_unique<device::GetAssertionRequestHandler>( request_ = std::make_unique<device::GetAssertionRequestHandler>(
connector_, protocols_, connector_, protocols_, std::move(ctap_request),
CreateCtapGetAssertionRequest(ConstructClientDataHash(client_data_json_),
std::move(options),
alternative_application_parameter_),
base::BindOnce(&AuthenticatorImpl::OnSignResponse, base::BindOnce(&AuthenticatorImpl::OnSignResponse,
weak_factory_.GetWeakPtr())); weak_factory_.GetWeakPtr()));
...@@ -585,7 +588,7 @@ void AuthenticatorImpl::GetAssertion( ...@@ -585,7 +588,7 @@ void AuthenticatorImpl::GetAssertion(
request_->set_observer(request_delegate_.get()); request_->set_observer(request_delegate_.get());
request_->SetPlatformAuthenticatorOrMarkUnavailable( request_->SetPlatformAuthenticatorOrMarkUnavailable(
CreatePlatformAuthenticatorIfAvailable()); std::move(opt_platform_authenticator_info));
} }
void AuthenticatorImpl::IsUserVerifyingPlatformAuthenticatorAvailable( void AuthenticatorImpl::IsUserVerifyingPlatformAuthenticatorAvailable(
...@@ -852,26 +855,56 @@ BrowserContext* AuthenticatorImpl::browser_context() const { ...@@ -852,26 +855,56 @@ BrowserContext* AuthenticatorImpl::browser_context() const {
->GetBrowserContext(); ->GetBrowserContext();
} }
std::unique_ptr<device::FidoAuthenticator>
AuthenticatorImpl::CreatePlatformAuthenticatorIfAvailable() {
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
// Incognito mode disables platform authenticators, so check for availability namespace {
// first. std::unique_ptr<device::fido::mac::TouchIdAuthenticator>
if (!IsUserVerifyingPlatformAuthenticatorAvailableImpl()) { CreateTouchIdAuthenticatorIfAvailable(
return nullptr; const AuthenticatorRequestClientDelegate* request_delegate) {
}
// Not all embedders may provide an authenticator config. // Not all embedders may provide an authenticator config.
auto opt_authenticator_config = auto opt_authenticator_config =
request_delegate_->GetTouchIdAuthenticatorConfig(); request_delegate->GetTouchIdAuthenticatorConfig();
if (!opt_authenticator_config) { if (!opt_authenticator_config) {
return nullptr; return nullptr;
} }
return device::fido::mac::TouchIdAuthenticator::CreateIfAvailable( return device::fido::mac::TouchIdAuthenticator::CreateIfAvailable(
std::move(opt_authenticator_config->keychain_access_group), std::move(opt_authenticator_config->keychain_access_group),
std::move(opt_authenticator_config->metadata_secret)); std::move(opt_authenticator_config->metadata_secret));
}
} // namespace
#endif
base::Optional<device::PlatformAuthenticatorInfo>
AuthenticatorImpl::CreatePlatformAuthenticatorIfAvailable() {
// Incognito mode disables platform authenticators, so check for availability
// first.
if (!IsUserVerifyingPlatformAuthenticatorAvailableImpl()) {
return base::nullopt;
}
#if defined(OS_MACOSX)
return device::PlatformAuthenticatorInfo(
CreateTouchIdAuthenticatorIfAvailable(request_delegate_.get()), false);
#else
return base::nullopt;
#endif
}
base::Optional<device::PlatformAuthenticatorInfo> AuthenticatorImpl::
CreatePlatformAuthenticatorIfAvailableAndCheckIfCredentialExists(
const device::CtapGetAssertionRequest& request) {
// Incognito mode disables platform authenticators, so check for availability
// first.
if (!IsUserVerifyingPlatformAuthenticatorAvailableImpl()) {
return base::nullopt;
}
#if defined(OS_MACOSX)
std::unique_ptr<device::fido::mac::TouchIdAuthenticator> authenticator =
CreateTouchIdAuthenticatorIfAvailable(request_delegate_.get());
const bool has_credential =
authenticator->HasCredentialForGetAssertionRequest(request);
return device::PlatformAuthenticatorInfo(std::move(authenticator),
has_credential);
#else #else
return nullptr; return base::nullopt;
#endif #endif
} }
......
...@@ -31,7 +31,8 @@ class OneShotTimer; ...@@ -31,7 +31,8 @@ class OneShotTimer;
namespace device { namespace device {
class FidoAuthenticator; struct PlatformAuthenticatorInfo;
class CtapGetAssertionRequest;
class FidoRequestHandlerBase; class FidoRequestHandlerBase;
enum class FidoReturnCode : uint8_t; enum class FidoReturnCode : uint8_t;
...@@ -155,8 +156,11 @@ class CONTENT_EXPORT AuthenticatorImpl : public blink::mojom::Authenticator, ...@@ -155,8 +156,11 @@ class CONTENT_EXPORT AuthenticatorImpl : public blink::mojom::Authenticator,
blink::mojom::GetAssertionAuthenticatorResponsePtr response); blink::mojom::GetAssertionAuthenticatorResponsePtr response);
void Cleanup(); void Cleanup();
std::unique_ptr<device::FidoAuthenticator> base::Optional<device::PlatformAuthenticatorInfo>
CreatePlatformAuthenticatorIfAvailable(); CreatePlatformAuthenticatorIfAvailable();
base::Optional<device::PlatformAuthenticatorInfo>
CreatePlatformAuthenticatorIfAvailableAndCheckIfCredentialExists(
const device::CtapGetAssertionRequest& request);
BrowserContext* browser_context() const; BrowserContext* browser_context() const;
......
...@@ -19,6 +19,20 @@ ...@@ -19,6 +19,20 @@
namespace device { namespace device {
// PlatformAuthenticatorInfo --------------------------
PlatformAuthenticatorInfo::PlatformAuthenticatorInfo(
std::unique_ptr<FidoAuthenticator> authenticator_,
bool has_recognized_mac_touch_id_credential_)
: authenticator(std::move(authenticator_)),
has_recognized_mac_touch_id_credential(
has_recognized_mac_touch_id_credential_) {}
PlatformAuthenticatorInfo::PlatformAuthenticatorInfo(
PlatformAuthenticatorInfo&&) = default;
PlatformAuthenticatorInfo& PlatformAuthenticatorInfo::operator=(
PlatformAuthenticatorInfo&&) = default;
PlatformAuthenticatorInfo::~PlatformAuthenticatorInfo() = default;
// FidoRequestHandlerBase::TransportAvailabilityInfo -------------------------- // FidoRequestHandlerBase::TransportAvailabilityInfo --------------------------
FidoRequestHandlerBase::TransportAvailabilityInfo::TransportAvailabilityInfo() = FidoRequestHandlerBase::TransportAvailabilityInfo::TransportAvailabilityInfo() =
...@@ -208,13 +222,17 @@ void FidoRequestHandlerBase::AddAuthenticator( ...@@ -208,13 +222,17 @@ void FidoRequestHandlerBase::AddAuthenticator(
} }
void FidoRequestHandlerBase::SetPlatformAuthenticatorOrMarkUnavailable( void FidoRequestHandlerBase::SetPlatformAuthenticatorOrMarkUnavailable(
std::unique_ptr<FidoAuthenticator> authenticator) { base::Optional<PlatformAuthenticatorInfo> platform_authenticator_info) {
if (authenticator && if (platform_authenticator_info &&
base::ContainsKey(transport_availability_info_.available_transports, base::ContainsKey(transport_availability_info_.available_transports,
FidoTransportProtocol::kInternal)) { FidoTransportProtocol::kInternal)) {
DCHECK(authenticator->AuthenticatorTransport() == DCHECK(platform_authenticator_info->authenticator);
FidoTransportProtocol::kInternal); DCHECK(
AddAuthenticator(std::move(authenticator)); (platform_authenticator_info->authenticator->AuthenticatorTransport() ==
FidoTransportProtocol::kInternal));
transport_availability_info_.has_recognized_mac_touch_id_credential =
platform_authenticator_info->has_recognized_mac_touch_id_credential;
AddAuthenticator(std::move(platform_authenticator_info->authenticator));
} else { } else {
transport_availability_info_.available_transports.erase( transport_availability_info_.available_transports.erase(
FidoTransportProtocol::kInternal); FidoTransportProtocol::kInternal);
......
...@@ -33,6 +33,17 @@ class FidoAuthenticator; ...@@ -33,6 +33,17 @@ class FidoAuthenticator;
class FidoDevice; class FidoDevice;
class FidoTask; class FidoTask;
struct COMPONENT_EXPORT(DEVICE_FIDO) PlatformAuthenticatorInfo {
PlatformAuthenticatorInfo(std::unique_ptr<FidoAuthenticator> authenticator,
bool has_recognized_mac_touch_id_credential);
PlatformAuthenticatorInfo(PlatformAuthenticatorInfo&&);
PlatformAuthenticatorInfo& operator=(PlatformAuthenticatorInfo&& other);
~PlatformAuthenticatorInfo();
std::unique_ptr<FidoAuthenticator> authenticator;
bool has_recognized_mac_touch_id_credential;
};
// Base class that handles device discovery/removal. Each FidoRequestHandlerBase // Base class that handles device discovery/removal. Each FidoRequestHandlerBase
// is owned by FidoRequestManager and its lifetime is equivalent to that of a // is owned by FidoRequestManager and its lifetime is equivalent to that of a
// single WebAuthn request. For each authenticator, the per-device work is // single WebAuthn request. For each authenticator, the per-device work is
...@@ -126,7 +137,7 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoRequestHandlerBase ...@@ -126,7 +137,7 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoRequestHandlerBase
// |AuthenticatorImpl| must call this method after invoking |set_oberver| even // |AuthenticatorImpl| must call this method after invoking |set_oberver| even
// if no platform authenticator is available, in which case it passes nullptr. // if no platform authenticator is available, in which case it passes nullptr.
void SetPlatformAuthenticatorOrMarkUnavailable( void SetPlatformAuthenticatorOrMarkUnavailable(
std::unique_ptr<FidoAuthenticator> authenticator); base::Optional<PlatformAuthenticatorInfo> platform_authenticator_info);
TransportAvailabilityInfo& transport_availability_info() { TransportAvailabilityInfo& transport_availability_info() {
return transport_availability_info_; return transport_availability_info_;
......
...@@ -55,12 +55,18 @@ class TestTransportAvailabilityObserver ...@@ -55,12 +55,18 @@ class TestTransportAvailabilityObserver
~TestTransportAvailabilityObserver() override {} ~TestTransportAvailabilityObserver() override {}
void WaitForAndExpectAvailableTransportsAre( void WaitForAndExpectAvailableTransportsAre(
base::flat_set<FidoTransportProtocol> expected_transports) { base::flat_set<FidoTransportProtocol> expected_transports,
base::Optional<bool> has_recognized_mac_touch_id_credential =
base::nullopt) {
transport_availability_notification_receiver_.WaitForCallback(); transport_availability_notification_receiver_.WaitForCallback();
auto result = auto result =
std::get<0>(*transport_availability_notification_receiver_.result()); std::get<0>(*transport_availability_notification_receiver_.result());
EXPECT_THAT(result.available_transports, EXPECT_THAT(result.available_transports,
::testing::UnorderedElementsAreArray(expected_transports)); ::testing::UnorderedElementsAreArray(expected_transports));
if (has_recognized_mac_touch_id_credential) {
EXPECT_EQ(*has_recognized_mac_touch_id_credential,
result.has_recognized_mac_touch_id_credential);
}
} }
protected: protected:
...@@ -192,7 +198,7 @@ class FidoRequestHandlerTest : public ::testing::Test { ...@@ -192,7 +198,7 @@ class FidoRequestHandlerTest : public ::testing::Test {
{FidoTransportProtocol::kUsbHumanInterfaceDevice, {FidoTransportProtocol::kUsbHumanInterfaceDevice,
FidoTransportProtocol::kBluetoothLowEnergy}), FidoTransportProtocol::kBluetoothLowEnergy}),
cb_.callback()); cb_.callback());
handler->SetPlatformAuthenticatorOrMarkUnavailable(nullptr); handler->SetPlatformAuthenticatorOrMarkUnavailable(base::nullopt);
return handler; return handler;
} }
...@@ -403,10 +409,43 @@ TEST_F(FidoRequestHandlerTest, TestSetPlatformAuthenticator) { ...@@ -403,10 +409,43 @@ TEST_F(FidoRequestHandlerTest, TestSetPlatformAuthenticator) {
callback().callback()); callback().callback());
request_handler->set_observer(&observer); request_handler->set_observer(&observer);
request_handler->SetPlatformAuthenticatorOrMarkUnavailable( request_handler->SetPlatformAuthenticatorOrMarkUnavailable(
std::move(authenticator)); PlatformAuthenticatorInfo(std::move(authenticator), false));
observer.WaitForAndExpectAvailableTransportsAre(
{FidoTransportProtocol::kInternal},
false /* has_recognized_mac_touch_id_credential */);
callback().WaitForCallback();
EXPECT_TRUE(request_handler->is_complete());
EXPECT_EQ(FidoReturnCode::kSuccess, callback().status());
}
// SetPlatformAuthenticatorOrMarkUnavailable should propagate the
// has_recognized_mac_touch_id_credential field.
TEST_F(FidoRequestHandlerTest,
TestSetPlatformAuthenticatorHasTouchIdCredential) {
// A platform authenticator usually wouldn't usually use a FidoDevice, but
// that's not the point of the test here. The test is only trying to ensure
// the authenticator gets injected and used.
auto device = MockFidoDevice::MakeCtap();
EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device0"));
// Device returns success response.
device->ExpectRequestAndRespondWith(std::vector<uint8_t>(),
CreateFakeSuccessDeviceResponse());
device->SetDeviceTransport(FidoTransportProtocol::kInternal);
auto authenticator = std::make_unique<FakeFidoAuthenticator>(device.get());
TestTransportAvailabilityObserver observer;
auto request_handler = std::make_unique<FakeFidoRequestHandler>(
base::flat_set<FidoTransportProtocol>({FidoTransportProtocol::kInternal}),
callback().callback());
request_handler->set_observer(&observer);
request_handler->SetPlatformAuthenticatorOrMarkUnavailable(
PlatformAuthenticatorInfo(std::move(authenticator), true));
observer.WaitForAndExpectAvailableTransportsAre( observer.WaitForAndExpectAvailableTransportsAre(
{FidoTransportProtocol::kInternal}); {FidoTransportProtocol::kInternal},
true /* has_recognized_mac_touch_id_credential */);
callback().WaitForCallback(); callback().WaitForCallback();
EXPECT_TRUE(request_handler->is_complete()); EXPECT_TRUE(request_handler->is_complete());
...@@ -419,7 +458,7 @@ TEST_F(FidoRequestHandlerTest, InternalTransportDisallowedIfMarkedUnavailable) { ...@@ -419,7 +458,7 @@ TEST_F(FidoRequestHandlerTest, InternalTransportDisallowedIfMarkedUnavailable) {
base::flat_set<FidoTransportProtocol>({FidoTransportProtocol::kInternal}), base::flat_set<FidoTransportProtocol>({FidoTransportProtocol::kInternal}),
callback().callback()); callback().callback());
request_handler->set_observer(&observer); request_handler->set_observer(&observer);
request_handler->SetPlatformAuthenticatorOrMarkUnavailable(nullptr); request_handler->SetPlatformAuthenticatorOrMarkUnavailable(base::nullopt);
observer.WaitForAndExpectAvailableTransportsAre({}); observer.WaitForAndExpectAvailableTransportsAre({});
} }
......
...@@ -142,11 +142,12 @@ class FidoGetAssertionHandlerTest : public ::testing::Test { ...@@ -142,11 +142,12 @@ class FidoGetAssertionHandlerTest : public ::testing::Test {
} }
protected: protected:
std::unique_ptr<FidoAuthenticator> CreatePlatformAuthenticator() { base::Optional<PlatformAuthenticatorInfo> CreatePlatformAuthenticator() {
if (!mock_platform_device_) if (!mock_platform_device_)
return nullptr; return base::nullopt;
return std::make_unique<FidoDeviceAuthenticator>( return PlatformAuthenticatorInfo(
mock_platform_device_.get()); std::make_unique<FidoDeviceAuthenticator>(mock_platform_device_.get()),
false /* has_recognized_mac_touch_id_credential_available */);
} }
base::test::ScopedTaskEnvironment scoped_task_environment_{ base::test::ScopedTaskEnvironment scoped_task_environment_{
......
...@@ -44,6 +44,9 @@ class COMPONENT_EXPORT(DEVICE_FIDO) TouchIdAuthenticator ...@@ -44,6 +44,9 @@ class COMPONENT_EXPORT(DEVICE_FIDO) TouchIdAuthenticator
~TouchIdAuthenticator() override; ~TouchIdAuthenticator() override;
bool HasCredentialForGetAssertionRequest(
const CtapGetAssertionRequest& request);
// FidoAuthenticator // FidoAuthenticator
void MakeCredential(CtapMakeCredentialRequest request, void MakeCredential(CtapMakeCredentialRequest request,
MakeCredentialCallback callback) override; MakeCredentialCallback callback) override;
......
...@@ -4,12 +4,15 @@ ...@@ -4,12 +4,15 @@
#include "device/fido/mac/authenticator.h" #include "device/fido/mac/authenticator.h"
#include <algorithm>
#import <LocalAuthentication/LocalAuthentication.h> #import <LocalAuthentication/LocalAuthentication.h>
#include "base/feature_list.h" #include "base/feature_list.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "base/optional.h" #include "base/optional.h"
#include "base/stl_util.h"
#include "base/strings/string_piece.h" #include "base/strings/string_piece.h"
#include "device/base/features.h" #include "device/base/features.h"
#include "device/fido/authenticator_supported_options.h" #include "device/fido/authenticator_supported_options.h"
...@@ -55,6 +58,35 @@ std::unique_ptr<TouchIdAuthenticator> TouchIdAuthenticator::CreateForTesting( ...@@ -55,6 +58,35 @@ std::unique_ptr<TouchIdAuthenticator> TouchIdAuthenticator::CreateForTesting(
TouchIdAuthenticator::~TouchIdAuthenticator() = default; TouchIdAuthenticator::~TouchIdAuthenticator() = default;
bool TouchIdAuthenticator::HasCredentialForGetAssertionRequest(
const CtapGetAssertionRequest& request) {
if (__builtin_available(macOS 10.12.2, *)) {
std::set<std::vector<uint8_t>> allow_list_credential_ids;
// Extract applicable credential IDs from the allowList, if the request has
// one. If not, any credential matching the RP works.
if (request.allow_list()) {
for (const auto& credential_descriptor : *request.allow_list()) {
if (credential_descriptor.credential_type() !=
CredentialType::kPublicKey)
continue;
if (!credential_descriptor.transports().empty() &&
!base::ContainsKey(credential_descriptor.transports(),
FidoTransportProtocol::kInternal))
continue;
allow_list_credential_ids.insert(credential_descriptor.id());
}
}
return FindCredentialInKeychain(keychain_access_group_, metadata_secret_,
request.rp_id(), allow_list_credential_ids,
nullptr /* LAContext */) != base::nullopt;
}
NOTREACHED();
return false;
}
void TouchIdAuthenticator::MakeCredential(CtapMakeCredentialRequest request, void TouchIdAuthenticator::MakeCredential(CtapMakeCredentialRequest request,
MakeCredentialCallback callback) { MakeCredentialCallback callback) {
if (__builtin_available(macOS 10.12.2, *)) { if (__builtin_available(macOS 10.12.2, *)) {
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/mac/foundation_util.h" #include "base/mac/foundation_util.h"
#include "base/mac/mac_logging.h" #include "base/mac/mac_logging.h"
#include "base/mac/scoped_cftyperef.h" #include "base/mac/scoped_cftyperef.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "device/fido/fido_constants.h" #include "device/fido/fido_constants.h"
...@@ -55,9 +56,14 @@ void GetAssertionOperation::Run() { ...@@ -55,9 +56,14 @@ void GetAssertionOperation::Run() {
std::set<std::vector<uint8_t>> allowed_credential_ids; std::set<std::vector<uint8_t>> allowed_credential_ids;
if (request().allow_list()) { if (request().allow_list()) {
for (const PublicKeyCredentialDescriptor& desc : *request().allow_list()) { for (const PublicKeyCredentialDescriptor& desc : *request().allow_list()) {
if (desc.credential_type() != CredentialType::kPublicKey) { if (desc.credential_type() != CredentialType::kPublicKey)
continue; continue;
}
if (!desc.transports().empty() &&
!base::ContainsKey(desc.transports(),
FidoTransportProtocol::kInternal))
continue;
allowed_credential_ids.insert(desc.id()); allowed_credential_ids.insert(desc.id());
} }
} }
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "base/mac/foundation_util.h" #include "base/mac/foundation_util.h"
#include "base/mac/mac_logging.h" #include "base/mac/mac_logging.h"
#include "base/stl_util.h"
#include "base/strings/sys_string_conversions.h" #include "base/strings/sys_string_conversions.h"
#include "device/fido/mac/credential_metadata.h" #include "device/fido/mac/credential_metadata.h"
...@@ -135,7 +136,7 @@ base::Optional<Credential> FindCredentialInKeychain( ...@@ -135,7 +136,7 @@ base::Optional<Credential> FindCredentialInKeychain(
CFDataGetBytePtr(application_label) + CFDataGetBytePtr(application_label) +
CFDataGetLength(application_label)); CFDataGetLength(application_label));
if (credential_id_filter.empty() || if (credential_id_filter.empty() ||
credential_id_filter.find(cid) != credential_id_filter.end()) { base::ContainsKey(credential_id_filter, cid)) {
private_key.reset(key, base::scoped_policy::RETAIN); private_key.reset(key, base::scoped_policy::RETAIN);
credential_id = std::move(cid); credential_id = std::move(cid);
break; break;
......
...@@ -141,11 +141,12 @@ class FidoMakeCredentialHandlerTest : public ::testing::Test { ...@@ -141,11 +141,12 @@ class FidoMakeCredentialHandlerTest : public ::testing::Test {
} }
protected: protected:
std::unique_ptr<FidoAuthenticator> CreatePlatformAuthenticator() { base::Optional<PlatformAuthenticatorInfo> CreatePlatformAuthenticator() {
if (!mock_platform_device_) if (!mock_platform_device_)
return nullptr; return base::nullopt;
return std::make_unique<FidoDeviceAuthenticator>( return PlatformAuthenticatorInfo(
mock_platform_device_.get()); std::make_unique<FidoDeviceAuthenticator>(mock_platform_device_.get()),
false /* has_recognized_mac_touch_id_credential_available */);
} }
base::test::ScopedFeatureList scoped_feature_list_; base::test::ScopedFeatureList scoped_feature_list_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment