Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / content / browser / speech / speech_recognition_dispatcher_host.cc
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/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"
19
20 namespace content {
21
22 SpeechRecognitionDispatcherHost::SpeechRecognitionDispatcherHost(
23     bool is_guest,
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       weak_factory_(this) {
30   // Do not add any non-trivial initialization here, instead do it lazily when
31   // required (e.g. see the method |SpeechRecognitionManager::GetInstance()|) or
32   // add an Init() method.
33 }
34
35 SpeechRecognitionDispatcherHost::~SpeechRecognitionDispatcherHost() {
36   SpeechRecognitionManager::GetInstance()->AbortAllSessionsForRenderProcess(
37       render_process_id_);
38 }
39
40 base::WeakPtr<SpeechRecognitionDispatcherHost>
41 SpeechRecognitionDispatcherHost::AsWeakPtr() {
42   return weak_factory_.GetWeakPtr();
43 }
44
45 bool SpeechRecognitionDispatcherHost::OnMessageReceived(
46     const IPC::Message& message, bool* message_was_ok) {
47   bool handled = true;
48   IPC_BEGIN_MESSAGE_MAP_EX(SpeechRecognitionDispatcherHost, message,
49                            *message_was_ok)
50     IPC_MESSAGE_HANDLER(SpeechRecognitionHostMsg_StartRequest,
51                         OnStartRequest)
52     IPC_MESSAGE_HANDLER(SpeechRecognitionHostMsg_AbortRequest,
53                         OnAbortRequest)
54     IPC_MESSAGE_HANDLER(SpeechRecognitionHostMsg_StopCaptureRequest,
55                         OnStopCaptureRequest)
56     IPC_MESSAGE_UNHANDLED(handled = false)
57   IPC_END_MESSAGE_MAP()
58   return handled;
59 }
60
61 void SpeechRecognitionDispatcherHost::OverrideThreadForMessage(
62     const IPC::Message& message,
63     BrowserThread::ID* thread) {
64   if (message.type() == SpeechRecognitionHostMsg_StartRequest::ID)
65     *thread = BrowserThread::UI;
66 }
67
68 void SpeechRecognitionDispatcherHost::OnChannelClosing() {
69   weak_factory_.InvalidateWeakPtrs();
70 }
71
72 void SpeechRecognitionDispatcherHost::OnStartRequest(
73     const SpeechRecognitionHostMsg_StartRequest_Params& params) {
74   SpeechRecognitionHostMsg_StartRequest_Params input_params(params);
75
76   int embedder_render_process_id = 0;
77   int embedder_render_view_id = MSG_ROUTING_NONE;
78   if (is_guest_) {
79     // If the speech API request was from a guest, save the context of the
80     // embedder since we will use it to decide permission.
81     RenderViewHostImpl* render_view_host =
82         RenderViewHostImpl::FromID(render_process_id_, params.render_view_id);
83     WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
84         WebContents::FromRenderViewHost(render_view_host));
85     BrowserPluginGuest* guest = web_contents->GetBrowserPluginGuest();
86
87     embedder_render_process_id =
88         guest->embedder_web_contents()->GetRenderProcessHost()->GetID();
89     DCHECK_NE(embedder_render_process_id, 0);
90     embedder_render_view_id =
91         guest->embedder_web_contents()->GetRenderViewHost()->GetRoutingID();
92     DCHECK_NE(embedder_render_view_id, MSG_ROUTING_NONE);
93   }
94
95   // TODO(lazyboy): Check if filter_profanities should use |render_process_id|
96   // instead of |render_process_id_|. We are also using the same value in
97   // input_tag_dispatcher_host.cc
98   bool filter_profanities =
99       SpeechRecognitionManagerImpl::GetInstance() &&
100       SpeechRecognitionManagerImpl::GetInstance()->delegate() &&
101       SpeechRecognitionManagerImpl::GetInstance()->delegate()->
102           FilterProfanities(render_process_id_);
103
104   BrowserThread::PostTask(
105       BrowserThread::IO,
106       FROM_HERE,
107       base::Bind(&SpeechRecognitionDispatcherHost::OnStartRequestOnIO,
108                  this,
109                  embedder_render_process_id,
110                  embedder_render_view_id,
111                  input_params,
112                  filter_profanities));
113 }
114
115 void SpeechRecognitionDispatcherHost::OnStartRequestOnIO(
116     int embedder_render_process_id,
117     int embedder_render_view_id,
118     const SpeechRecognitionHostMsg_StartRequest_Params& params,
119     bool filter_profanities) {
120   SpeechRecognitionSessionContext context;
121   context.context_name = params.origin_url;
122   context.render_process_id = render_process_id_;
123   context.render_view_id = params.render_view_id;
124   context.embedder_render_process_id = embedder_render_process_id;
125   context.embedder_render_view_id = embedder_render_view_id;
126   if (embedder_render_process_id)
127     context.guest_render_view_id = params.render_view_id;
128   context.request_id = params.request_id;
129   context.requested_by_page_element = false;
130
131   SpeechRecognitionSessionConfig config;
132   config.is_legacy_api = false;
133   config.language = params.language;
134   config.grammars = params.grammars;
135   config.max_hypotheses = params.max_hypotheses;
136   config.origin_url = params.origin_url;
137   config.initial_context = context;
138   config.url_request_context_getter = context_getter_.get();
139   config.filter_profanities = filter_profanities;
140   config.continuous = params.continuous;
141   config.interim_results = params.interim_results;
142   config.event_listener = AsWeakPtr();
143
144   int session_id = SpeechRecognitionManager::GetInstance()->CreateSession(
145       config);
146   DCHECK_NE(session_id, SpeechRecognitionManager::kSessionIDInvalid);
147   SpeechRecognitionManager::GetInstance()->StartSession(session_id);
148 }
149
150 void SpeechRecognitionDispatcherHost::OnAbortRequest(int render_view_id,
151                                                      int request_id) {
152   int session_id = SpeechRecognitionManager::GetInstance()->GetSession(
153       render_process_id_, render_view_id, request_id);
154
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()->AbortSession(session_id);
159 }
160
161 void SpeechRecognitionDispatcherHost::OnStopCaptureRequest(
162     int render_view_id, int request_id) {
163   int session_id = SpeechRecognitionManager::GetInstance()->GetSession(
164       render_process_id_, render_view_id, request_id);
165
166   // The renderer might provide an invalid |request_id| if the session was not
167   // started as expected, e.g., due to unsatisfied security requirements.
168   if (session_id != SpeechRecognitionManager::kSessionIDInvalid) {
169     SpeechRecognitionManager::GetInstance()->StopAudioCaptureForSession(
170         session_id);
171   }
172 }
173
174 // -------- SpeechRecognitionEventListener interface implementation -----------
175
176 void SpeechRecognitionDispatcherHost::OnRecognitionStart(int session_id) {
177   const SpeechRecognitionSessionContext& context =
178       SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
179   Send(new SpeechRecognitionMsg_Started(context.render_view_id,
180                                         context.request_id));
181 }
182
183 void SpeechRecognitionDispatcherHost::OnAudioStart(int session_id) {
184   const SpeechRecognitionSessionContext& context =
185       SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
186   Send(new SpeechRecognitionMsg_AudioStarted(context.render_view_id,
187                                              context.request_id));
188 }
189
190 void SpeechRecognitionDispatcherHost::OnSoundStart(int session_id) {
191   const SpeechRecognitionSessionContext& context =
192       SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
193   Send(new SpeechRecognitionMsg_SoundStarted(context.render_view_id,
194                                              context.request_id));
195 }
196
197 void SpeechRecognitionDispatcherHost::OnSoundEnd(int session_id) {
198   const SpeechRecognitionSessionContext& context =
199       SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
200   Send(new SpeechRecognitionMsg_SoundEnded(context.render_view_id,
201                                            context.request_id));
202 }
203
204 void SpeechRecognitionDispatcherHost::OnAudioEnd(int session_id) {
205   const SpeechRecognitionSessionContext& context =
206       SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
207   Send(new SpeechRecognitionMsg_AudioEnded(context.render_view_id,
208                                            context.request_id));
209 }
210
211 void SpeechRecognitionDispatcherHost::OnRecognitionEnd(int session_id) {
212   const SpeechRecognitionSessionContext& context =
213       SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
214   Send(new SpeechRecognitionMsg_Ended(context.render_view_id,
215                                       context.request_id));
216 }
217
218 void SpeechRecognitionDispatcherHost::OnRecognitionResults(
219     int session_id,
220     const SpeechRecognitionResults& results) {
221   const SpeechRecognitionSessionContext& context =
222       SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
223   Send(new SpeechRecognitionMsg_ResultRetrieved(context.render_view_id,
224                                                 context.request_id,
225                                                 results));
226 }
227
228 void SpeechRecognitionDispatcherHost::OnRecognitionError(
229     int session_id,
230     const SpeechRecognitionError& error) {
231   const SpeechRecognitionSessionContext& context =
232       SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
233   Send(new SpeechRecognitionMsg_ErrorOccurred(context.render_view_id,
234                                               context.request_id,
235                                               error));
236 }
237
238 // The events below are currently not used by speech JS APIs implementation.
239 void SpeechRecognitionDispatcherHost::OnAudioLevelsChange(int session_id,
240                                                           float volume,
241                                                           float noise_volume) {
242 }
243
244 void SpeechRecognitionDispatcherHost::OnEnvironmentEstimationComplete(
245     int session_id) {
246 }
247
248 }  // namespace content