- add sources.
[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   // 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.
32 }
33
34 SpeechRecognitionDispatcherHost::~SpeechRecognitionDispatcherHost() {
35   SpeechRecognitionManager::GetInstance()->AbortAllSessionsForListener(this);
36 }
37
38 bool SpeechRecognitionDispatcherHost::OnMessageReceived(
39     const IPC::Message& message, bool* message_was_ok) {
40   bool handled = true;
41   IPC_BEGIN_MESSAGE_MAP_EX(SpeechRecognitionDispatcherHost, message,
42                            *message_was_ok)
43     IPC_MESSAGE_HANDLER(SpeechRecognitionHostMsg_StartRequest,
44                         OnStartRequest)
45     IPC_MESSAGE_HANDLER(SpeechRecognitionHostMsg_AbortRequest,
46                         OnAbortRequest)
47     IPC_MESSAGE_HANDLER(SpeechRecognitionHostMsg_StopCaptureRequest,
48                         OnStopCaptureRequest)
49     IPC_MESSAGE_UNHANDLED(handled = false)
50   IPC_END_MESSAGE_MAP()
51   return handled;
52 }
53
54 void SpeechRecognitionDispatcherHost::OverrideThreadForMessage(
55     const IPC::Message& message,
56     BrowserThread::ID* thread) {
57   if (message.type() == SpeechRecognitionHostMsg_StartRequest::ID)
58     *thread = BrowserThread::UI;
59 }
60
61 void SpeechRecognitionDispatcherHost::OnStartRequest(
62     const SpeechRecognitionHostMsg_StartRequest_Params& params) {
63   SpeechRecognitionHostMsg_StartRequest_Params input_params(params);
64
65   int embedder_render_process_id = 0;
66   int embedder_render_view_id = MSG_ROUTING_NONE;
67   if (is_guest_) {
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();
75
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);
82   }
83
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_);
92
93   BrowserThread::PostTask(
94       BrowserThread::IO,
95       FROM_HERE,
96       base::Bind(&SpeechRecognitionDispatcherHost::OnStartRequestOnIO,
97                  this,
98                  embedder_render_process_id,
99                  embedder_render_view_id,
100                  input_params,
101                  filter_profanities));
102 }
103
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;
119
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;
132
133   int session_id = SpeechRecognitionManager::GetInstance()->CreateSession(
134       config);
135   DCHECK_NE(session_id, SpeechRecognitionManager::kSessionIDInvalid);
136   SpeechRecognitionManager::GetInstance()->StartSession(session_id);
137 }
138
139 void SpeechRecognitionDispatcherHost::OnAbortRequest(int render_view_id,
140                                                      int request_id) {
141   int session_id = SpeechRecognitionManager::GetInstance()->GetSession(
142       render_process_id_, render_view_id, request_id);
143
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);
148 }
149
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);
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()->StopAudioCaptureForSession(
159         session_id);
160   }
161 }
162
163 // -------- SpeechRecognitionEventListener interface implementation -----------
164
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));
170 }
171
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));
177 }
178
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));
184 }
185
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));
191 }
192
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));
198 }
199
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));
205 }
206
207 void SpeechRecognitionDispatcherHost::OnRecognitionResults(
208     int session_id,
209     const SpeechRecognitionResults& results) {
210   const SpeechRecognitionSessionContext& context =
211       SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
212   Send(new SpeechRecognitionMsg_ResultRetrieved(context.render_view_id,
213                                                 context.request_id,
214                                                 results));
215 }
216
217 void SpeechRecognitionDispatcherHost::OnRecognitionError(
218     int session_id,
219     const SpeechRecognitionError& error) {
220   const SpeechRecognitionSessionContext& context =
221       SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
222   Send(new SpeechRecognitionMsg_ErrorOccurred(context.render_view_id,
223                                               context.request_id,
224                                               error));
225 }
226
227 // The events below are currently not used by speech JS APIs implementation.
228 void SpeechRecognitionDispatcherHost::OnAudioLevelsChange(int session_id,
229                                                           float volume,
230                                                           float noise_volume) {
231 }
232
233 void SpeechRecognitionDispatcherHost::OnEnvironmentEstimationComplete(
234     int session_id) {
235 }
236
237 }  // namespace content