| // 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/speech/chrome_speech_recognition_service.h" |
| |
| #include "base/metrics/histogram_functions.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/component_updater/soda_language_pack_component_installer.h" |
| #include "chrome/grit/generated_resources.h" |
| #include "components/live_caption/pref_names.h" |
| #include "components/prefs/pref_service.h" |
| #include "components/soda/constants.h" |
| #include "components/user_prefs/user_prefs.h" |
| #include "content/public/browser/browser_context.h" |
| #include "content/public/browser/service_process_host.h" |
| #include "content/public/browser/storage_partition.h" |
| #include "media/base/media_switches.h" |
| #include "media/mojo/mojom/speech_recognition_service.mojom.h" |
| #include "services/network/network_context.h" |
| #include "services/network/public/cpp/shared_url_loader_factory.h" |
| |
| namespace speech { |
| |
| constexpr base::TimeDelta kIdleProcessTimeout = base::Seconds(5); |
| |
| ChromeSpeechRecognitionService::ChromeSpeechRecognitionService( |
| content::BrowserContext* context) |
| : context_(context) {} |
| |
| ChromeSpeechRecognitionService::~ChromeSpeechRecognitionService() = default; |
| |
| void ChromeSpeechRecognitionService::Create( |
| mojo::PendingReceiver<media::mojom::SpeechRecognitionContext> receiver) { |
| LaunchIfNotRunning(); |
| |
| if (speech_recognition_service_.is_bound()) |
| speech_recognition_service_->BindContext(std::move(receiver)); |
| } |
| |
| void ChromeSpeechRecognitionService::LaunchIfNotRunning() { |
| if (speech_recognition_service_.is_bound()) |
| return; |
| |
| PrefService* profile_prefs = user_prefs::UserPrefs::Get(context_); |
| PrefService* global_prefs = g_browser_process->local_state(); |
| DCHECK(profile_prefs); |
| DCHECK(global_prefs); |
| |
| base::FilePath binary_path, config_path; |
| binary_path = global_prefs->GetFilePath(prefs::kSodaBinaryPath); |
| config_path = |
| ChromeSpeechRecognitionService::GetSodaConfigPath(profile_prefs); |
| if (binary_path.empty() || config_path.empty()) { |
| LOG(ERROR) << "Unable to find SODA files on the device."; |
| return; |
| } |
| |
| content::ServiceProcessHost::Launch( |
| speech_recognition_service_.BindNewPipeAndPassReceiver(), |
| content::ServiceProcessHost::Options() |
| .WithDisplayName(IDS_UTILITY_PROCESS_SPEECH_RECOGNITION_SERVICE_NAME) |
| .Pass()); |
| |
| // Ensure that if the interface is ever disconnected (e.g. the service |
| // process crashes) or goes idle for a short period of time -- meaning there |
| // are no in-flight messages and no other interfaces bound through this |
| // one -- then we will reset |remote|, causing the service process to be |
| // terminated if it isn't already. |
| speech_recognition_service_.reset_on_disconnect(); |
| speech_recognition_service_.reset_on_idle_timeout(kIdleProcessTimeout); |
| speech_recognition_service_->SetSodaPath(binary_path, config_path); |
| } |
| |
| base::FilePath ChromeSpeechRecognitionService::GetSodaConfigPath( |
| PrefService* prefs) { |
| // TODO(crbug.com/1161569): Language pack path should be configurable per |
| // SpeechRecognitionRecognizer to allow multiple features to use Speech |
| // recognition. For now, only Live Caption uses SpeechRecognitionService on |
| // non-Chrome OS Chrome, so hard-coding to the Live Caption language code. |
| absl::optional<speech::SodaLanguagePackComponentConfig> language_config = |
| speech::GetLanguageComponentConfig( |
| prefs::GetLiveCaptionLanguageCode(prefs)); |
| |
| if (language_config) { |
| base::UmaHistogramEnumeration("Accessibility.LiveCaption.SodaLanguage", |
| language_config.value().language_code); |
| return g_browser_process->local_state()->GetFilePath( |
| language_config.value().config_path_pref); |
| } |
| |
| return base::FilePath(); |
| } |
| } // namespace speech |