blob: 5d55104336e5a5bfafd45550fcabfea8e05a4f68 [file] [log] [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/soda/soda_util.h"
#include <string>
#include "base/feature_list.h"
#include "build/build_config.h"
#include "components/soda/constants.h"
#include "components/soda/soda_installer.h"
#include "media/base/media_switches.h"
#include "media/mojo/mojom/speech_recognizer.mojom.h"
#include "ui/base/l10n/l10n_util.h"
#if BUILDFLAG(IS_CHROMEOS)
#include "ash/constants/ash_features.h"
#include "base/feature_list.h"
#endif
#if BUILDFLAG(IS_WIN)
#include "base/win/windows_version.h"
#endif
#if BUILDFLAG(IS_LINUX) && defined(ARCH_CPU_X86_FAMILY)
#include "base/cpu.h"
#endif
namespace speech {
namespace {
#if BUILDFLAG(IS_CHROMEOS)
bool IsSupportedChromeOS() {
// Some Chrome OS devices do not support on-device speech.
return base::FeatureList::IsEnabled(
ash::features::kOnDeviceSpeechRecognition);
}
#endif // BUILDFLAG(IS_CHROMEOS)
#if BUILDFLAG(IS_LINUX)
bool IsSupportedLinux() {
#if defined(ARCH_CPU_X86_FAMILY)
// Check if the CPU has the required instruction set to run the Speech
// On-Device API (SODA) library.
static bool has_sse41 = base::CPU().has_sse41();
return has_sse41;
#else
// Other architectures are not supported.
return false;
#endif // defined(ARCH_CPU_X86_FAMILY)
}
#endif // BUILDFLAG(IS_LINUX)
#if BUILDFLAG(IS_WIN)
bool IsSupportedWin() {
#if defined(ARCH_CPU_ARM64)
// The Speech On-Device API (SODA) component does not support Windows on
// arm64.
return false;
#else
return true;
#endif // defined(ARCH_CPU_ARM64)
}
#endif // BUILDFLAG(IS_WIN)
} // namespace
bool IsOnDeviceSpeechRecognitionSupported() {
#if BUILDFLAG(IS_CHROMEOS)
return IsSupportedChromeOS();
#elif BUILDFLAG(IS_LINUX)
return IsSupportedLinux();
#elif BUILDFLAG(IS_WIN)
return IsSupportedWin();
#else
return true;
#endif
}
media::mojom::AvailabilityStatus IsOnDeviceSpeechRecognitionAvailable(
const std::string& language) {
if (!base::FeatureList::IsEnabled(media::kOnDeviceWebSpeech) ||
!IsOnDeviceSpeechRecognitionSupported()) {
return media::mojom::AvailabilityStatus::kUnavailable;
}
speech::SodaInstaller* soda_installer = speech::SodaInstaller::GetInstance();
DCHECK(soda_installer);
// Check whether the language supported.
bool is_language_supported = false;
speech::LanguageCode lang_code = speech::LanguageCode::kNone;
for (auto const& available_lang : soda_installer->GetAvailableLanguages()) {
if (l10n_util::GetLanguage(available_lang) ==
l10n_util::GetLanguage(language)) {
is_language_supported = true;
lang_code = speech::GetLanguageCode(available_lang);
break;
}
}
if (!is_language_supported) {
return media::mojom::AvailabilityStatus::kUnavailable;
}
if (soda_installer->IsSodaInstalled(lang_code)) {
return media::mojom::AvailabilityStatus::kAvailable;
}
if (soda_installer->IsLanguageEnabled(language)) {
// By this point the language must be either be available but not yet
// installed or currently downloading.
if (soda_installer->IsSodaLanguageDownloading(
speech::GetLanguageCode(language))) {
return media::mojom::AvailabilityStatus::kDownloading;
}
return media::mojom::AvailabilityStatus::kDownloadable;
}
return media::mojom::AvailabilityStatus::kUnavailable;
}
} // namespace speech