// Copyright (c) 2012 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 "content/browser/speech/speech_recognition_dispatcher_host.h" #include "base/bind.h" #include "base/command_line.h" #include "base/lazy_instance.h" #include "content/common/speech_recognition_messages.h" #include "content/public/browser/speech_recognition_manager.h" #include "content/public/browser/speech_recognition_preferences.h" #include "content/public/browser/speech_recognition_session_config.h" #include "content/public/browser/speech_recognition_session_context.h" #include "content/public/common/content_switches.h" using content::SpeechRecognitionManager; using content::SpeechRecognitionSessionConfig; using content::SpeechRecognitionSessionContext; namespace speech { SpeechRecognitionManager* SpeechRecognitionDispatcherHost::manager_for_tests_; void SpeechRecognitionDispatcherHost::SetManagerForTests( SpeechRecognitionManager* manager) { manager_for_tests_ = manager; } SpeechRecognitionDispatcherHost::SpeechRecognitionDispatcherHost( int render_process_id, net::URLRequestContextGetter* context_getter, content::SpeechRecognitionPreferences* recognition_preferences) : render_process_id_(render_process_id), context_getter_(context_getter), recognition_preferences_(recognition_preferences) { // Do not add any non-trivial initialization here, instead do it lazily when // required (e.g. see the method |manager()|) or add an Init() method. } SpeechRecognitionDispatcherHost::~SpeechRecognitionDispatcherHost() { if (SpeechRecognitionManager* sr_manager = manager()) sr_manager->AbortAllSessionsForListener(this); } SpeechRecognitionManager* SpeechRecognitionDispatcherHost::manager() { if (manager_for_tests_) return manager_for_tests_; const CommandLine& command_line = *CommandLine::ForCurrentProcess(); if (command_line.HasSwitch(switches::kEnableScriptedSpeech)) return SpeechRecognitionManager::GetInstance(); return NULL; } bool SpeechRecognitionDispatcherHost::OnMessageReceived( const IPC::Message& message, bool* message_was_ok) { bool handled = true; IPC_BEGIN_MESSAGE_MAP_EX(SpeechRecognitionDispatcherHost, message, *message_was_ok) IPC_MESSAGE_HANDLER(SpeechRecognitionHostMsg_StartRequest, OnStartRequest) IPC_MESSAGE_HANDLER(SpeechRecognitionHostMsg_AbortRequest, OnAbortRequest) IPC_MESSAGE_HANDLER(SpeechRecognitionHostMsg_StopCaptureRequest, OnStopCaptureRequest) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; } void SpeechRecognitionDispatcherHost::OnStartRequest( const SpeechRecognitionHostMsg_StartRequest_Params& params) { SpeechRecognitionSessionContext context; context.context_name = params.origin_url; context.render_process_id = render_process_id_; context.render_view_id = params.render_view_id; context.request_id = params.request_id; context.requested_by_page_element = false; SpeechRecognitionSessionConfig config; config.is_one_shot = params.is_one_shot; config.language = params.language; config.grammars = params.grammars; config.origin_url = params.origin_url; config.initial_context = context; config.url_request_context_getter = context_getter_.get(); if (recognition_preferences_) { config.filter_profanities = recognition_preferences_->FilterProfanities(); } else { config.filter_profanities = false; } config.event_listener = this; int session_id = manager()->CreateSession(config); DCHECK_NE(session_id, content::SpeechRecognitionManager::kSessionIDInvalid); manager()->StartSession(session_id); } void SpeechRecognitionDispatcherHost::OnAbortRequest(int render_view_id, int request_id) { int session_id = manager()->GetSession(render_process_id_, render_view_id, request_id); // The renderer might provide an invalid |request_id| if the session was not // started as expected, e.g., due to unsatisfied security requirements. if (session_id != content::SpeechRecognitionManager::kSessionIDInvalid) manager()->AbortSession(session_id); } void SpeechRecognitionDispatcherHost::OnStopCaptureRequest( int render_view_id, int request_id) { int session_id = manager()->GetSession(render_process_id_, render_view_id, request_id); // The renderer might provide an invalid |request_id| if the session was not // started as expected, e.g., due to unsatisfied security requirements. if (session_id != content::SpeechRecognitionManager::kSessionIDInvalid) manager()->StopAudioCaptureForSession(session_id); } // -------- SpeechRecognitionEventListener interface implementation ----------- void SpeechRecognitionDispatcherHost::OnRecognitionStart(int session_id) { const SpeechRecognitionSessionContext& context = manager()->GetSessionContext(session_id); Send(new SpeechRecognitionMsg_Started(context.render_view_id, context.request_id)); } void SpeechRecognitionDispatcherHost::OnAudioStart(int session_id) { const SpeechRecognitionSessionContext& context = manager()->GetSessionContext(session_id); Send(new SpeechRecognitionMsg_AudioStarted(context.render_view_id, context.request_id)); } void SpeechRecognitionDispatcherHost::OnSoundStart(int session_id) { const SpeechRecognitionSessionContext& context = manager()->GetSessionContext(session_id); Send(new SpeechRecognitionMsg_SoundStarted(context.render_view_id, context.request_id)); } void SpeechRecognitionDispatcherHost::OnSoundEnd(int session_id) { const SpeechRecognitionSessionContext& context = manager()->GetSessionContext(session_id); Send(new SpeechRecognitionMsg_SoundEnded(context.render_view_id, context.request_id)); } void SpeechRecognitionDispatcherHost::OnAudioEnd(int session_id) { const SpeechRecognitionSessionContext& context = manager()->GetSessionContext(session_id); Send(new SpeechRecognitionMsg_AudioEnded(context.render_view_id, context.request_id)); } void SpeechRecognitionDispatcherHost::OnRecognitionEnd(int session_id) { const SpeechRecognitionSessionContext& context = manager()->GetSessionContext(session_id); Send(new SpeechRecognitionMsg_Ended(context.render_view_id, context.request_id)); } void SpeechRecognitionDispatcherHost::OnRecognitionResult( int session_id, const content::SpeechRecognitionResult& result) { const SpeechRecognitionSessionContext& context = manager()->GetSessionContext(session_id); Send(new SpeechRecognitionMsg_ResultRetrieved(context.render_view_id, context.request_id, result)); } void SpeechRecognitionDispatcherHost::OnRecognitionError( int session_id, const content::SpeechRecognitionError& error) { const SpeechRecognitionSessionContext& context = manager()->GetSessionContext(session_id); Send(new SpeechRecognitionMsg_ErrorOccurred(context.render_view_id, context.request_id, error)); } // The events below are currently not used by speech JS APIs implementation. void SpeechRecognitionDispatcherHost::OnAudioLevelsChange( int session_id, float volume, float noise_volume) {} void SpeechRecognitionDispatcherHost::OnEnvironmentEstimationComplete( int session_id) {} } // namespace speech