Update To 11.40.268.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/child_process_security_policy_impl.h"
12 #include "content/browser/renderer_host/render_view_host_impl.h"
13 #include "content/browser/speech/speech_recognition_manager_impl.h"
14 #include "content/browser/web_contents/web_contents_impl.h"
15 #include "content/common/speech_recognition_messages.h"
16 #include "content/public/browser/speech_recognition_manager_delegate.h"
17 #include "content/public/browser/speech_recognition_session_config.h"
18 #include "content/public/browser/speech_recognition_session_context.h"
19 #include "content/public/common/content_switches.h"
20
21 namespace content {
22
23 SpeechRecognitionDispatcherHost::SpeechRecognitionDispatcherHost(
24     int render_process_id,
25     net::URLRequestContextGetter* context_getter)
26     : BrowserMessageFilter(SpeechRecognitionMsgStart),
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 void SpeechRecognitionDispatcherHost::OnDestruct() const {
46   BrowserThread::DeleteOnIOThread::Destruct(this);
47 }
48
49 bool SpeechRecognitionDispatcherHost::OnMessageReceived(
50     const IPC::Message& message) {
51   bool handled = true;
52   IPC_BEGIN_MESSAGE_MAP(SpeechRecognitionDispatcherHost, message)
53     IPC_MESSAGE_HANDLER(SpeechRecognitionHostMsg_StartRequest,
54                         OnStartRequest)
55     IPC_MESSAGE_HANDLER(SpeechRecognitionHostMsg_AbortRequest,
56                         OnAbortRequest)
57     IPC_MESSAGE_HANDLER(SpeechRecognitionHostMsg_StopCaptureRequest,
58                         OnStopCaptureRequest)
59     IPC_MESSAGE_HANDLER(SpeechRecognitionHostMsg_AbortAllRequests,
60                         OnAbortAllRequests)
61     IPC_MESSAGE_UNHANDLED(handled = false)
62   IPC_END_MESSAGE_MAP()
63   return handled;
64 }
65
66 void SpeechRecognitionDispatcherHost::OverrideThreadForMessage(
67     const IPC::Message& message,
68     BrowserThread::ID* thread) {
69   if (message.type() == SpeechRecognitionHostMsg_StartRequest::ID)
70     *thread = BrowserThread::UI;
71 }
72
73 void SpeechRecognitionDispatcherHost::OnChannelClosing() {
74   weak_factory_.InvalidateWeakPtrs();
75 }
76
77 void SpeechRecognitionDispatcherHost::OnStartRequest(
78     const SpeechRecognitionHostMsg_StartRequest_Params& params) {
79   SpeechRecognitionHostMsg_StartRequest_Params input_params(params);
80
81   // Check that the origin specified by the renderer process is one
82   // that it is allowed to access.
83   if (params.origin_url != "null" &&
84       !ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL(
85           render_process_id_, GURL(params.origin_url))) {
86     LOG(ERROR) << "SRDH::OnStartRequest, disallowed origin: "
87                << params.origin_url;
88     return;
89   }
90
91   int embedder_render_process_id = 0;
92   int embedder_render_view_id = MSG_ROUTING_NONE;
93   RenderViewHostImpl* render_view_host =
94       RenderViewHostImpl::FromID(render_process_id_, params.render_view_id);
95   if (!render_view_host) {
96     // RVH can be null if the tab was closed while continuous mode speech
97     // recognition was running. This seems to happen on mac.
98     LOG(WARNING) << "SRDH::OnStartRequest, RenderViewHost does not exist";
99     return;
100   }
101   WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
102       WebContents::FromRenderViewHost(render_view_host));
103   BrowserPluginGuest* guest = web_contents->GetBrowserPluginGuest();
104   if (guest) {
105     // If the speech API request was from a guest, save the context of the
106     // embedder since we will use it to decide permission.
107     embedder_render_process_id =
108         guest->embedder_web_contents()->GetRenderProcessHost()->GetID();
109     DCHECK_NE(embedder_render_process_id, 0);
110     embedder_render_view_id =
111         guest->embedder_web_contents()->GetRenderViewHost()->GetRoutingID();
112     DCHECK_NE(embedder_render_view_id, MSG_ROUTING_NONE);
113   }
114
115   // TODO(lazyboy): Check if filter_profanities should use |render_process_id|
116   // instead of |render_process_id_|.
117   bool filter_profanities =
118       SpeechRecognitionManagerImpl::GetInstance() &&
119       SpeechRecognitionManagerImpl::GetInstance()->delegate() &&
120       SpeechRecognitionManagerImpl::GetInstance()->delegate()->
121           FilterProfanities(render_process_id_);
122
123   // TODO(miu): This is a hack to allow SpeechRecognition to operate with the
124   // MediaStreamManager, which partitions requests per RenderFrame, not per
125   // RenderView.  http://crbug.com/390749
126   const int params_render_frame_id = render_view_host ?
127       render_view_host->GetMainFrame()->GetRoutingID() : MSG_ROUTING_NONE;
128
129   BrowserThread::PostTask(
130       BrowserThread::IO,
131       FROM_HERE,
132       base::Bind(&SpeechRecognitionDispatcherHost::OnStartRequestOnIO,
133                  this,
134                  embedder_render_process_id,
135                  embedder_render_view_id,
136                  input_params,
137                  params_render_frame_id,
138                  filter_profanities));
139 }
140
141 void SpeechRecognitionDispatcherHost::OnStartRequestOnIO(
142     int embedder_render_process_id,
143     int embedder_render_view_id,
144     const SpeechRecognitionHostMsg_StartRequest_Params& params,
145     int params_render_frame_id,
146     bool filter_profanities) {
147   SpeechRecognitionSessionContext context;
148   context.context_name = params.origin_url;
149   context.render_process_id = render_process_id_;
150   context.render_view_id = params.render_view_id;
151   context.render_frame_id = params_render_frame_id;
152   context.embedder_render_process_id = embedder_render_process_id;
153   context.embedder_render_view_id = embedder_render_view_id;
154   if (embedder_render_process_id)
155     context.guest_render_view_id = params.render_view_id;
156   context.request_id = params.request_id;
157
158   SpeechRecognitionSessionConfig config;
159   config.is_legacy_api = false;
160   config.language = params.language;
161   config.grammars = params.grammars;
162   config.max_hypotheses = params.max_hypotheses;
163   config.origin_url = params.origin_url;
164   config.initial_context = context;
165   config.url_request_context_getter = context_getter_.get();
166   config.filter_profanities = filter_profanities;
167   config.continuous = params.continuous;
168   config.interim_results = params.interim_results;
169   config.event_listener = AsWeakPtr();
170
171   int session_id = SpeechRecognitionManager::GetInstance()->CreateSession(
172       config);
173   DCHECK_NE(session_id, SpeechRecognitionManager::kSessionIDInvalid);
174   SpeechRecognitionManager::GetInstance()->StartSession(session_id);
175 }
176
177 void SpeechRecognitionDispatcherHost::OnAbortRequest(int render_view_id,
178                                                      int request_id) {
179   int session_id = SpeechRecognitionManager::GetInstance()->GetSession(
180       render_process_id_, render_view_id, request_id);
181
182   // The renderer might provide an invalid |request_id| if the session was not
183   // started as expected, e.g., due to unsatisfied security requirements.
184   if (session_id != SpeechRecognitionManager::kSessionIDInvalid)
185     SpeechRecognitionManager::GetInstance()->AbortSession(session_id);
186 }
187
188 void SpeechRecognitionDispatcherHost::OnAbortAllRequests(int render_view_id) {
189   SpeechRecognitionManager::GetInstance()->AbortAllSessionsForRenderView(
190       render_process_id_, render_view_id);
191 }
192
193 void SpeechRecognitionDispatcherHost::OnStopCaptureRequest(
194     int render_view_id, int request_id) {
195   int session_id = SpeechRecognitionManager::GetInstance()->GetSession(
196       render_process_id_, render_view_id, request_id);
197
198   // The renderer might provide an invalid |request_id| if the session was not
199   // started as expected, e.g., due to unsatisfied security requirements.
200   if (session_id != SpeechRecognitionManager::kSessionIDInvalid) {
201     SpeechRecognitionManager::GetInstance()->StopAudioCaptureForSession(
202         session_id);
203   }
204 }
205
206 // -------- SpeechRecognitionEventListener interface implementation -----------
207
208 void SpeechRecognitionDispatcherHost::OnRecognitionStart(int session_id) {
209   const SpeechRecognitionSessionContext& context =
210       SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
211   Send(new SpeechRecognitionMsg_Started(context.render_view_id,
212                                         context.request_id));
213 }
214
215 void SpeechRecognitionDispatcherHost::OnAudioStart(int session_id) {
216   const SpeechRecognitionSessionContext& context =
217       SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
218   Send(new SpeechRecognitionMsg_AudioStarted(context.render_view_id,
219                                              context.request_id));
220 }
221
222 void SpeechRecognitionDispatcherHost::OnSoundStart(int session_id) {
223   const SpeechRecognitionSessionContext& context =
224       SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
225   Send(new SpeechRecognitionMsg_SoundStarted(context.render_view_id,
226                                              context.request_id));
227 }
228
229 void SpeechRecognitionDispatcherHost::OnSoundEnd(int session_id) {
230   const SpeechRecognitionSessionContext& context =
231       SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
232   Send(new SpeechRecognitionMsg_SoundEnded(context.render_view_id,
233                                            context.request_id));
234 }
235
236 void SpeechRecognitionDispatcherHost::OnAudioEnd(int session_id) {
237   const SpeechRecognitionSessionContext& context =
238       SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
239   Send(new SpeechRecognitionMsg_AudioEnded(context.render_view_id,
240                                            context.request_id));
241 }
242
243 void SpeechRecognitionDispatcherHost::OnRecognitionEnd(int session_id) {
244   const SpeechRecognitionSessionContext& context =
245       SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
246   Send(new SpeechRecognitionMsg_Ended(context.render_view_id,
247                                       context.request_id));
248 }
249
250 void SpeechRecognitionDispatcherHost::OnRecognitionResults(
251     int session_id,
252     const SpeechRecognitionResults& results) {
253   const SpeechRecognitionSessionContext& context =
254       SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
255   Send(new SpeechRecognitionMsg_ResultRetrieved(context.render_view_id,
256                                                 context.request_id,
257                                                 results));
258 }
259
260 void SpeechRecognitionDispatcherHost::OnRecognitionError(
261     int session_id,
262     const SpeechRecognitionError& error) {
263   const SpeechRecognitionSessionContext& context =
264       SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
265   Send(new SpeechRecognitionMsg_ErrorOccurred(context.render_view_id,
266                                               context.request_id,
267                                               error));
268 }
269
270 // The events below are currently not used by speech JS APIs implementation.
271 void SpeechRecognitionDispatcherHost::OnAudioLevelsChange(int session_id,
272                                                           float volume,
273                                                           float noise_volume) {
274 }
275
276 void SpeechRecognitionDispatcherHost::OnEnvironmentEstimationComplete(
277     int session_id) {
278 }
279
280 }  // namespace content