1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "content/browser/speech/speech_recognition_dispatcher_host.h" 6 7 #include "base/bind.h" 8 #include "base/command_line.h" 9 #include "base/lazy_instance.h" 10 #include "content/browser/speech/speech_recognition_manager_impl.h" 11 #include "content/common/speech_recognition_messages.h" 12 #include "content/public/browser/speech_recognition_manager_delegate.h" 13 #include "content/public/browser/speech_recognition_session_config.h" 14 #include "content/public/browser/speech_recognition_session_context.h" 15 #include "content/public/common/content_switches.h" 16 17 namespace content { 18 19 SpeechRecognitionDispatcherHost::SpeechRecognitionDispatcherHost( 20 int render_process_id, 21 net::URLRequestContextGetter* context_getter) 22 : render_process_id_(render_process_id), 23 context_getter_(context_getter) { 24 // Do not add any non-trivial initialization here, instead do it lazily when 25 // required (e.g. see the method |SpeechRecognitionManager::GetInstance()|) or 26 // add an Init() method. 27 } 28 29 SpeechRecognitionDispatcherHost::~SpeechRecognitionDispatcherHost() { 30 SpeechRecognitionManager::GetInstance()->AbortAllSessionsForListener(this); 31 } 32 33 bool SpeechRecognitionDispatcherHost::OnMessageReceived( 34 const IPC::Message& message, bool* message_was_ok) { 35 bool handled = true; 36 IPC_BEGIN_MESSAGE_MAP_EX(SpeechRecognitionDispatcherHost, message, 37 *message_was_ok) 38 IPC_MESSAGE_HANDLER(SpeechRecognitionHostMsg_StartRequest, 39 OnStartRequest) 40 IPC_MESSAGE_HANDLER(SpeechRecognitionHostMsg_AbortRequest, 41 OnAbortRequest) 42 IPC_MESSAGE_HANDLER(SpeechRecognitionHostMsg_StopCaptureRequest, 43 OnStopCaptureRequest) 44 IPC_MESSAGE_UNHANDLED(handled = false) 45 IPC_END_MESSAGE_MAP() 46 return handled; 47 } 48 49 void SpeechRecognitionDispatcherHost::OverrideThreadForMessage( 50 const IPC::Message& message, 51 BrowserThread::ID* thread) { 52 if (message.type() == SpeechRecognitionHostMsg_StartRequest::ID) 53 *thread = BrowserThread::UI; 54 } 55 56 void SpeechRecognitionDispatcherHost::OnStartRequest( 57 const SpeechRecognitionHostMsg_StartRequest_Params& params) { 58 bool filter_profanities = 59 SpeechRecognitionManagerImpl::GetInstance() && 60 SpeechRecognitionManagerImpl::GetInstance()->delegate() && 61 SpeechRecognitionManagerImpl::GetInstance()->delegate()-> 62 FilterProfanities(render_process_id_); 63 64 BrowserThread::PostTask( 65 BrowserThread::IO, 66 FROM_HERE, 67 base::Bind(&SpeechRecognitionDispatcherHost::OnStartRequestOnIO, 68 this, params, filter_profanities)); 69 } 70 71 void SpeechRecognitionDispatcherHost::OnStartRequestOnIO( 72 const SpeechRecognitionHostMsg_StartRequest_Params& params, 73 bool filter_profanities) { 74 SpeechRecognitionSessionContext context; 75 context.context_name = params.origin_url; 76 context.render_process_id = render_process_id_; 77 context.render_view_id = params.render_view_id; 78 context.request_id = params.request_id; 79 context.requested_by_page_element = false; 80 81 SpeechRecognitionSessionConfig config; 82 config.is_legacy_api = false; 83 config.language = params.language; 84 config.grammars = params.grammars; 85 config.max_hypotheses = params.max_hypotheses; 86 config.origin_url = params.origin_url; 87 config.initial_context = context; 88 config.url_request_context_getter = context_getter_.get(); 89 config.filter_profanities = filter_profanities; 90 config.continuous = params.continuous; 91 config.interim_results = params.interim_results; 92 config.event_listener = this; 93 94 int session_id = SpeechRecognitionManager::GetInstance()->CreateSession( 95 config); 96 DCHECK_NE(session_id, SpeechRecognitionManager::kSessionIDInvalid); 97 SpeechRecognitionManager::GetInstance()->StartSession(session_id); 98 } 99 100 void SpeechRecognitionDispatcherHost::OnAbortRequest(int render_view_id, 101 int request_id) { 102 int session_id = SpeechRecognitionManager::GetInstance()->GetSession( 103 render_process_id_, render_view_id, request_id); 104 105 // The renderer might provide an invalid |request_id| if the session was not 106 // started as expected, e.g., due to unsatisfied security requirements. 107 if (session_id != SpeechRecognitionManager::kSessionIDInvalid) 108 SpeechRecognitionManager::GetInstance()->AbortSession(session_id); 109 } 110 111 void SpeechRecognitionDispatcherHost::OnStopCaptureRequest( 112 int render_view_id, int request_id) { 113 int session_id = SpeechRecognitionManager::GetInstance()->GetSession( 114 render_process_id_, render_view_id, request_id); 115 116 // The renderer might provide an invalid |request_id| if the session was not 117 // started as expected, e.g., due to unsatisfied security requirements. 118 if (session_id != SpeechRecognitionManager::kSessionIDInvalid) { 119 SpeechRecognitionManager::GetInstance()->StopAudioCaptureForSession( 120 session_id); 121 } 122 } 123 124 // -------- SpeechRecognitionEventListener interface implementation ----------- 125 126 void SpeechRecognitionDispatcherHost::OnRecognitionStart(int session_id) { 127 const SpeechRecognitionSessionContext& context = 128 SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id); 129 Send(new SpeechRecognitionMsg_Started(context.render_view_id, 130 context.request_id)); 131 } 132 133 void SpeechRecognitionDispatcherHost::OnAudioStart(int session_id) { 134 const SpeechRecognitionSessionContext& context = 135 SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id); 136 Send(new SpeechRecognitionMsg_AudioStarted(context.render_view_id, 137 context.request_id)); 138 } 139 140 void SpeechRecognitionDispatcherHost::OnSoundStart(int session_id) { 141 const SpeechRecognitionSessionContext& context = 142 SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id); 143 Send(new SpeechRecognitionMsg_SoundStarted(context.render_view_id, 144 context.request_id)); 145 } 146 147 void SpeechRecognitionDispatcherHost::OnSoundEnd(int session_id) { 148 const SpeechRecognitionSessionContext& context = 149 SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id); 150 Send(new SpeechRecognitionMsg_SoundEnded(context.render_view_id, 151 context.request_id)); 152 } 153 154 void SpeechRecognitionDispatcherHost::OnAudioEnd(int session_id) { 155 const SpeechRecognitionSessionContext& context = 156 SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id); 157 Send(new SpeechRecognitionMsg_AudioEnded(context.render_view_id, 158 context.request_id)); 159 } 160 161 void SpeechRecognitionDispatcherHost::OnRecognitionEnd(int session_id) { 162 const SpeechRecognitionSessionContext& context = 163 SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id); 164 Send(new SpeechRecognitionMsg_Ended(context.render_view_id, 165 context.request_id)); 166 } 167 168 void SpeechRecognitionDispatcherHost::OnRecognitionResults( 169 int session_id, 170 const SpeechRecognitionResults& results) { 171 const SpeechRecognitionSessionContext& context = 172 SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id); 173 Send(new SpeechRecognitionMsg_ResultRetrieved(context.render_view_id, 174 context.request_id, 175 results)); 176 } 177 178 void SpeechRecognitionDispatcherHost::OnRecognitionError( 179 int session_id, 180 const SpeechRecognitionError& error) { 181 const SpeechRecognitionSessionContext& context = 182 SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id); 183 Send(new SpeechRecognitionMsg_ErrorOccurred(context.render_view_id, 184 context.request_id, 185 error)); 186 } 187 188 // The events below are currently not used by speech JS APIs implementation. 189 void SpeechRecognitionDispatcherHost::OnAudioLevelsChange(int session_id, 190 float volume, 191 float noise_volume) { 192 } 193 194 void SpeechRecognitionDispatcherHost::OnEnvironmentEstimationComplete( 195 int session_id) { 196 } 197 198 } // namespace content 199