blob: c3fd6a4919ab0801db3d6f1e1d022a3996f398eb [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/metrics/authenticator_utility.h"
#include <memory>
#include "base/bind.h"
#include "base/metrics/histogram_functions.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/webauthn/chrome_authenticator_request_delegate.h"
#include "content/public/browser/authenticator_request_client_delegate.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/is_uvpaa.h"
#if defined(OS_MAC)
#include "device/fido/mac/authenticator.h"
#endif
#if defined(OS_WIN)
#include "device/fido/win/webauthn_api.h"
#endif
namespace authenticator_utility {
void ReportAvailability(bool available) {
base::UmaHistogramBoolean(
"WebAuthentication.IsUVPlatformAuthenticatorAvailable", available);
}
#if defined(OS_MAC)
void ReportUVPlatformAuthenticatorAvailabilityWithConfig(
base::Optional<device::fido::mac::AuthenticatorConfig> config) {
ReportAvailability(config &&
content::IsUVPlatformAuthenticatorAvailable(*config));
}
void ReportUVPlatformAuthenticatorAvailabilityMainThreadMac() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
// Tests can shut down before this task is run.
if (!g_browser_process)
return;
// Startup metrics are recording during PostBrowserStart() which is after
// profile initialization. However some tests run PostBrowserStart() without
// setting up profiles so there still needs to be a guard.
ProfileManager* profile_manager = g_browser_process->profile_manager();
if (!profile_manager || !g_browser_process->local_state()) {
return;
}
Profile* profile = profile_manager->GetProfileByPath(
profile_manager->GetLastUsedProfileDir(profile_manager->user_data_dir()));
DCHECK(profile);
// Return to a low-priority thread for the actual check.
base::ThreadPool::PostTask(
FROM_HERE, {base::TaskPriority::BEST_EFFORT},
base::BindOnce(&ReportUVPlatformAuthenticatorAvailabilityWithConfig,
ChromeAuthenticatorRequestDelegate::
TouchIdAuthenticatorConfigForProfile(profile)));
}
#endif
void ReportUVPlatformAuthenticatorAvailability() {
// This only reports metrics for desktop platforms. For mobile devices, the
// platform version is an exact proxy for whether a platform authenticator
// can be used.
#if defined(OS_MAC)
DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
// Getting the profile has to be done on the main thread to avoid race
// conditions.
content::GetUIThreadTaskRunner({base::TaskPriority::BEST_EFFORT})
->PostTask(FROM_HERE,
base::BindOnce(
&ReportUVPlatformAuthenticatorAvailabilityMainThreadMac));
#elif defined(OS_WIN)
std::unique_ptr<content::AuthenticatorRequestClientDelegate> client_delegate =
std::make_unique<content::AuthenticatorRequestClientDelegate>();
device::WinWebAuthnApi* win_webauthn_api =
device::WinWebAuthnApi::GetDefault();
ReportAvailability(
win_webauthn_api &&
content::IsUVPlatformAuthenticatorAvailable(win_webauthn_api));
#elif BUILDFLAG(IS_CHROMEOS_ASH)
ReportAvailability(content::IsUVPlatformAuthenticatorAvailable());
#endif
}
} // namespace authenticator_utility