123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- // 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 "components/soda/soda_installer.h"
- #include "base/containers/contains.h"
- #include "base/feature_list.h"
- #include "base/observer_list.h"
- #include "base/values.h"
- #include "build/chromeos_buildflags.h"
- #include "components/live_caption/pref_names.h"
- #include "components/prefs/pref_service.h"
- #include "components/prefs/scoped_user_pref_update.h"
- #include "components/soda/constants.h"
- #include "components/soda/pref_names.h"
- #include "media/base/media_switches.h"
- #if BUILDFLAG(IS_CHROMEOS_ASH)
- #include "ash/constants/ash_features.h"
- #include "ash/constants/ash_pref_names.h"
- #endif // BUILDFLAG(IS_CHROMEOS_ASH)
- namespace {
- constexpr int kSodaCleanUpDelayInDays = 30;
- #if BUILDFLAG(IS_CHROMEOS_ASH)
- inline std::string GetProjectorLanguageCode(PrefService* pref_service) {
- return pref_service->GetString(ash::prefs::kProjectorCreationFlowLanguage);
- }
- #endif // IS_CHROMEOS_ASH
- } // namespace
- namespace speech {
- SodaInstaller* g_instance = nullptr;
- // static
- SodaInstaller* SodaInstaller::GetInstance() {
- #if BUILDFLAG(IS_CHROMEOS_ASH)
- DCHECK(
- base::FeatureList::IsEnabled(ash::features::kOnDeviceSpeechRecognition));
- #endif // BUILDFLAG(IS_CHROMEOS_ASH)
- return g_instance;
- }
- SodaInstaller::SodaInstaller() {
- DCHECK_EQ(nullptr, g_instance);
- g_instance = this;
- }
- SodaInstaller::~SodaInstaller() {
- DCHECK_EQ(this, g_instance);
- g_instance = nullptr;
- }
- // static
- void SodaInstaller::RegisterLocalStatePrefs(PrefRegistrySimple* registry) {
- registry->RegisterTimePref(prefs::kSodaScheduledDeletionTime, base::Time());
- SodaInstaller::RegisterRegisteredLanguagePackPref(registry);
- #if !BUILDFLAG(IS_CHROMEOS_ASH)
- // Handle non-Chrome-OS logic here. We need to keep the implementation of this
- // method in the parent class to avoid duplicate declaration build errors
- // (specifically on Windows).
- registry->RegisterFilePathPref(prefs::kSodaBinaryPath, base::FilePath());
- // Register language pack config path preferences.
- for (const SodaLanguagePackComponentConfig& config :
- kLanguageComponentConfigs) {
- registry->RegisterFilePathPref(config.config_path_pref, base::FilePath());
- }
- #endif // !BUILDFLAG(IS_CHROMEOS_ASH)
- }
- void SodaInstaller::Init(PrefService* profile_prefs,
- PrefService* global_prefs) {
- #if BUILDFLAG(IS_CHROMEOS_ASH)
- if (!base::FeatureList::IsEnabled(
- ash::features::kOnDeviceSpeechRecognition) ||
- soda_installer_initialized_) {
- #else // !BUILDFLAG(IS_CHROMEOS_ASH)
- if (soda_installer_initialized_) {
- #endif
- return;
- }
- if (IsAnyFeatureUsingSodaEnabled(profile_prefs)) {
- soda_installer_initialized_ = true;
- // Set the SODA uninstaller time to NULL time so that it doesn't get
- // uninstalled when features are using it.
- global_prefs->SetTime(prefs::kSodaScheduledDeletionTime, base::Time());
- SodaInstaller::GetInstance()->InstallSoda(global_prefs);
- if (global_prefs->GetValueList(prefs::kSodaRegisteredLanguagePacks)
- .empty()) {
- // TODO(crbug.com/1200667): Register the default language used by
- // Dictation on ChromeOS.
- #if BUILDFLAG(IS_CHROMEOS_ASH)
- RegisterLanguage(GetProjectorLanguageCode(profile_prefs), global_prefs);
- #endif // BUILDFLAG(IS_CHROMEOS_ASH)
- RegisterLanguage(prefs::GetLiveCaptionLanguageCode(profile_prefs),
- global_prefs);
- }
- for (const auto& language :
- global_prefs->GetValueList(prefs::kSodaRegisteredLanguagePacks)) {
- SodaInstaller::GetInstance()->InstallLanguage(language.GetString(),
- global_prefs);
- }
- } else {
- base::Time deletion_time =
- global_prefs->GetTime(prefs::kSodaScheduledDeletionTime);
- if (!deletion_time.is_null() && deletion_time <= base::Time::Now()) {
- UninstallSoda(global_prefs);
- soda_installer_initialized_ = false;
- }
- }
- }
- void SodaInstaller::SetUninstallTimer(PrefService* profile_prefs,
- PrefService* global_prefs) {
- // Do not schedule uninstallation if any SODA client features are still
- // enabled.
- if (IsAnyFeatureUsingSodaEnabled(profile_prefs))
- return;
- // Schedule deletion.
- global_prefs->SetTime(
- prefs::kSodaScheduledDeletionTime,
- base::Time::Now() + base::Days(kSodaCleanUpDelayInDays));
- }
- bool SodaInstaller::IsSodaInstalled(LanguageCode language_code) const {
- return (soda_binary_installed_ && IsLanguageInstalled(language_code));
- }
- bool SodaInstaller::IsLanguageInstalled(LanguageCode language_code) const {
- return base::Contains(installed_languages_, language_code);
- }
- void SodaInstaller::AddObserver(Observer* observer) {
- observers_.AddObserver(observer);
- }
- void SodaInstaller::RemoveObserver(Observer* observer) {
- observers_.RemoveObserver(observer);
- }
- void SodaInstaller::NotifySodaInstalledForTesting(LanguageCode language_code) {
- // TODO: Call the actual functions in SodaInstallerImpl and
- // SodaInstallerImpleChromeOS that do this logic
- // (e.g. SodaInstallerImpl::OnSodaBinaryInstalled) rather than faking it.
- // If language code is none, this signifies that the SODA binary installed.
- if (language_code == LanguageCode::kNone) {
- soda_binary_installed_ = true;
- is_soda_downloading_ = false;
- for (LanguageCode installed_language : installed_languages_) {
- NotifyOnSodaInstalled(installed_language);
- }
- return;
- }
- // Otherwise, this means a language pack installed.
- installed_languages_.insert(language_code);
- if (base::Contains(language_pack_progress_, language_code))
- language_pack_progress_.erase(language_code);
- if (soda_binary_installed_)
- NotifyOnSodaInstalled(language_code);
- }
- void SodaInstaller::NotifySodaErrorForTesting(LanguageCode language_code,
- ErrorCode error_code) {
- // TODO: Call the actual functions in SodaInstallerImpl and
- // SodaInstallerImpleChromeOS that do this logic rather than faking it.
- if (language_code == LanguageCode::kNone) {
- // Error with the SODA binary download.
- soda_binary_installed_ = false;
- is_soda_downloading_ = false;
- language_pack_progress_.clear();
- } else {
- // Error with the language pack download.
- if (base::Contains(language_pack_progress_, language_code))
- language_pack_progress_.erase(language_code);
- }
- NotifyOnSodaInstallError(language_code, error_code);
- }
- void SodaInstaller::UninstallSodaForTesting() {
- soda_binary_installed_ = false;
- is_soda_downloading_ = false;
- soda_installer_initialized_ = false;
- installed_languages_.clear();
- language_pack_progress_.clear();
- }
- void SodaInstaller::NotifySodaProgressForTesting(int progress,
- LanguageCode language_code) {
- // TODO: Call the actual functions in SodaInstallerImpl and
- // SodaInstallerImpleChromeOS that do this logic rather than faking it.
- if (language_code == LanguageCode::kNone) {
- // SODA binary download progress.
- soda_binary_installed_ = false;
- is_soda_downloading_ = true;
- } else {
- // Language pack download progress.
- if (base::Contains(language_pack_progress_, language_code))
- language_pack_progress_.insert({language_code, progress});
- else
- language_pack_progress_[language_code] = progress;
- }
- NotifyOnSodaProgress(language_code, progress);
- }
- bool SodaInstaller::IsAnyLanguagePackInstalledForTesting() const {
- return !installed_languages_.empty();
- }
- void SodaInstaller::RegisterRegisteredLanguagePackPref(
- PrefRegistrySimple* registry) {
- // TODO: Default to one of the user's languages.
- base::Value::List default_languages;
- default_languages.Append(base::Value(kUsEnglishLocale));
- registry->RegisterListPref(prefs::kSodaRegisteredLanguagePacks,
- std::move(default_languages));
- }
- void SodaInstaller::NotifyOnSodaInstalled(LanguageCode language_code) {
- for (Observer& observer : observers_)
- observer.OnSodaInstalled(language_code);
- }
- void SodaInstaller::NotifyOnSodaInstallError(LanguageCode language_code,
- ErrorCode error_code) {
- for (Observer& observer : observers_)
- observer.OnSodaInstallError(language_code, error_code);
- }
- void SodaInstaller::NotifyOnSodaProgress(LanguageCode language_code,
- int progress) {
- for (Observer& observer : observers_)
- observer.OnSodaProgress(language_code, progress);
- }
- void SodaInstaller::RegisterLanguage(const std::string& language,
- PrefService* global_prefs) {
- ListPrefUpdate update(global_prefs, prefs::kSodaRegisteredLanguagePacks);
- if (!base::Contains(update->GetList(), base::Value(language))) {
- update->GetList().Append(language);
- }
- }
- void SodaInstaller::UnregisterLanguages(PrefService* global_prefs) {
- ListPrefUpdate update(global_prefs, prefs::kSodaRegisteredLanguagePacks);
- update->GetList().clear();
- }
- bool SodaInstaller::IsSodaDownloading(LanguageCode language_code) const {
- return is_soda_downloading_ ||
- base::Contains(language_pack_progress_, language_code);
- }
- bool SodaInstaller::IsAnyFeatureUsingSodaEnabled(PrefService* prefs) {
- #if BUILDFLAG(IS_CHROMEOS_ASH)
- return prefs->GetBoolean(prefs::kLiveCaptionEnabled) ||
- prefs->GetBoolean(ash::prefs::kAccessibilityDictationEnabled) ||
- prefs->GetBoolean(ash::prefs::kProjectorCreationFlowEnabled);
- #else // !BUILDFLAG(IS_CHROMEOS_ASH)
- return prefs->GetBoolean(prefs::kLiveCaptionEnabled);
- #endif
- }
- } // namespace speech
|