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.
5 #include "content/browser/speech/speech_recognition_dispatcher_host.h"
8 #include "base/command_line.h"
9 #include "base/lazy_instance.h"
10 #include "content/browser/browser_plugin/browser_plugin_guest.h"
11 #include "content/browser/renderer_host/render_view_host_impl.h"
12 #include "content/browser/speech/speech_recognition_manager_impl.h"
13 #include "content/browser/web_contents/web_contents_impl.h"
14 #include "content/common/speech_recognition_messages.h"
15 #include "content/public/browser/speech_recognition_manager_delegate.h"
16 #include "content/public/browser/speech_recognition_session_config.h"
17 #include "content/public/browser/speech_recognition_session_context.h"
18 #include "content/public/common/content_switches.h"
22 SpeechRecognitionDispatcherHost::SpeechRecognitionDispatcherHost(
24 int render_process_id
,
25 net::URLRequestContextGetter
* context_getter
)
26 : is_guest_(is_guest
),
27 render_process_id_(render_process_id
),
28 context_getter_(context_getter
) {
29 // Do not add any non-trivial initialization here, instead do it lazily when
30 // required (e.g. see the method |SpeechRecognitionManager::GetInstance()|) or
31 // add an Init() method.
34 SpeechRecognitionDispatcherHost::~SpeechRecognitionDispatcherHost() {
35 SpeechRecognitionManager::GetInstance()->AbortAllSessionsForListener(this);
38 bool SpeechRecognitionDispatcherHost::OnMessageReceived(
39 const IPC::Message
& message
, bool* message_was_ok
) {
41 IPC_BEGIN_MESSAGE_MAP_EX(SpeechRecognitionDispatcherHost
, message
,
43 IPC_MESSAGE_HANDLER(SpeechRecognitionHostMsg_StartRequest
,
45 IPC_MESSAGE_HANDLER(SpeechRecognitionHostMsg_AbortRequest
,
47 IPC_MESSAGE_HANDLER(SpeechRecognitionHostMsg_StopCaptureRequest
,
49 IPC_MESSAGE_UNHANDLED(handled
= false)
54 void SpeechRecognitionDispatcherHost::OverrideThreadForMessage(
55 const IPC::Message
& message
,
56 BrowserThread::ID
* thread
) {
57 if (message
.type() == SpeechRecognitionHostMsg_StartRequest::ID
)
58 *thread
= BrowserThread::UI
;
61 void SpeechRecognitionDispatcherHost::OnStartRequest(
62 const SpeechRecognitionHostMsg_StartRequest_Params
& params
) {
63 SpeechRecognitionHostMsg_StartRequest_Params
input_params(params
);
65 int embedder_render_process_id
= 0;
66 int embedder_render_view_id
= MSG_ROUTING_NONE
;
68 // If the speech API request was from a guest, save the context of the
69 // embedder since we will use it to decide permission.
70 RenderViewHostImpl
* render_view_host
=
71 RenderViewHostImpl::FromID(render_process_id_
, params
.render_view_id
);
72 WebContentsImpl
* web_contents
= static_cast<WebContentsImpl
*>(
73 WebContents::FromRenderViewHost(render_view_host
));
74 BrowserPluginGuest
* guest
= web_contents
->GetBrowserPluginGuest();
76 embedder_render_process_id
=
77 guest
->embedder_web_contents()->GetRenderProcessHost()->GetID();
78 DCHECK_NE(embedder_render_process_id
, 0);
79 embedder_render_view_id
=
80 guest
->embedder_web_contents()->GetRenderViewHost()->GetRoutingID();
81 DCHECK_NE(embedder_render_view_id
, MSG_ROUTING_NONE
);
84 // TODO(lazyboy): Check if filter_profanities should use |render_process_id|
85 // instead of |render_process_id_|. We are also using the same value in
86 // input_tag_dispatcher_host.cc
87 bool filter_profanities
=
88 SpeechRecognitionManagerImpl::GetInstance() &&
89 SpeechRecognitionManagerImpl::GetInstance()->delegate() &&
90 SpeechRecognitionManagerImpl::GetInstance()->delegate()->
91 FilterProfanities(render_process_id_
);
93 BrowserThread::PostTask(
96 base::Bind(&SpeechRecognitionDispatcherHost::OnStartRequestOnIO
,
98 embedder_render_process_id
,
99 embedder_render_view_id
,
101 filter_profanities
));
104 void SpeechRecognitionDispatcherHost::OnStartRequestOnIO(
105 int embedder_render_process_id
,
106 int embedder_render_view_id
,
107 const SpeechRecognitionHostMsg_StartRequest_Params
& params
,
108 bool filter_profanities
) {
109 SpeechRecognitionSessionContext context
;
110 context
.context_name
= params
.origin_url
;
111 context
.render_process_id
= render_process_id_
;
112 context
.render_view_id
= params
.render_view_id
;
113 context
.embedder_render_process_id
= embedder_render_process_id
;
114 context
.embedder_render_view_id
= embedder_render_view_id
;
115 if (embedder_render_process_id
)
116 context
.guest_render_view_id
= params
.render_view_id
;
117 context
.request_id
= params
.request_id
;
118 context
.requested_by_page_element
= false;
120 SpeechRecognitionSessionConfig config
;
121 config
.is_legacy_api
= false;
122 config
.language
= params
.language
;
123 config
.grammars
= params
.grammars
;
124 config
.max_hypotheses
= params
.max_hypotheses
;
125 config
.origin_url
= params
.origin_url
;
126 config
.initial_context
= context
;
127 config
.url_request_context_getter
= context_getter_
.get();
128 config
.filter_profanities
= filter_profanities
;
129 config
.continuous
= params
.continuous
;
130 config
.interim_results
= params
.interim_results
;
131 config
.event_listener
= this;
133 int session_id
= SpeechRecognitionManager::GetInstance()->CreateSession(
135 DCHECK_NE(session_id
, SpeechRecognitionManager::kSessionIDInvalid
);
136 SpeechRecognitionManager::GetInstance()->StartSession(session_id
);
139 void SpeechRecognitionDispatcherHost::OnAbortRequest(int render_view_id
,
141 int session_id
= SpeechRecognitionManager::GetInstance()->GetSession(
142 render_process_id_
, render_view_id
, request_id
);
144 // The renderer might provide an invalid |request_id| if the session was not
145 // started as expected, e.g., due to unsatisfied security requirements.
146 if (session_id
!= SpeechRecognitionManager::kSessionIDInvalid
)
147 SpeechRecognitionManager::GetInstance()->AbortSession(session_id
);
150 void SpeechRecognitionDispatcherHost::OnStopCaptureRequest(
151 int render_view_id
, int request_id
) {
152 int session_id
= SpeechRecognitionManager::GetInstance()->GetSession(
153 render_process_id_
, render_view_id
, request_id
);
155 // The renderer might provide an invalid |request_id| if the session was not
156 // started as expected, e.g., due to unsatisfied security requirements.
157 if (session_id
!= SpeechRecognitionManager::kSessionIDInvalid
) {
158 SpeechRecognitionManager::GetInstance()->StopAudioCaptureForSession(
163 // -------- SpeechRecognitionEventListener interface implementation -----------
165 void SpeechRecognitionDispatcherHost::OnRecognitionStart(int session_id
) {
166 const SpeechRecognitionSessionContext
& context
=
167 SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id
);
168 Send(new SpeechRecognitionMsg_Started(context
.render_view_id
,
169 context
.request_id
));
172 void SpeechRecognitionDispatcherHost::OnAudioStart(int session_id
) {
173 const SpeechRecognitionSessionContext
& context
=
174 SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id
);
175 Send(new SpeechRecognitionMsg_AudioStarted(context
.render_view_id
,
176 context
.request_id
));
179 void SpeechRecognitionDispatcherHost::OnSoundStart(int session_id
) {
180 const SpeechRecognitionSessionContext
& context
=
181 SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id
);
182 Send(new SpeechRecognitionMsg_SoundStarted(context
.render_view_id
,
183 context
.request_id
));
186 void SpeechRecognitionDispatcherHost::OnSoundEnd(int session_id
) {
187 const SpeechRecognitionSessionContext
& context
=
188 SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id
);
189 Send(new SpeechRecognitionMsg_SoundEnded(context
.render_view_id
,
190 context
.request_id
));
193 void SpeechRecognitionDispatcherHost::OnAudioEnd(int session_id
) {
194 const SpeechRecognitionSessionContext
& context
=
195 SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id
);
196 Send(new SpeechRecognitionMsg_AudioEnded(context
.render_view_id
,
197 context
.request_id
));
200 void SpeechRecognitionDispatcherHost::OnRecognitionEnd(int session_id
) {
201 const SpeechRecognitionSessionContext
& context
=
202 SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id
);
203 Send(new SpeechRecognitionMsg_Ended(context
.render_view_id
,
204 context
.request_id
));
207 void SpeechRecognitionDispatcherHost::OnRecognitionResults(
209 const SpeechRecognitionResults
& results
) {
210 const SpeechRecognitionSessionContext
& context
=
211 SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id
);
212 Send(new SpeechRecognitionMsg_ResultRetrieved(context
.render_view_id
,
217 void SpeechRecognitionDispatcherHost::OnRecognitionError(
219 const SpeechRecognitionError
& error
) {
220 const SpeechRecognitionSessionContext
& context
=
221 SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id
);
222 Send(new SpeechRecognitionMsg_ErrorOccurred(context
.render_view_id
,
227 // The events below are currently not used by speech JS APIs implementation.
228 void SpeechRecognitionDispatcherHost::OnAudioLevelsChange(int session_id
,
230 float noise_volume
) {
233 void SpeechRecognitionDispatcherHost::OnEnvironmentEstimationComplete(
237 } // namespace content