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