OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/speech/speech_recognition_manager_impl.h" | 5 #include "content/browser/speech/speech_recognition_manager_impl.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "content/browser/browser_main_loop.h" | 8 #include "content/browser/browser_main_loop.h" |
9 #include "content/browser/speech/google_one_shot_remote_engine.h" | 9 #include "content/browser/speech/google_one_shot_remote_engine.h" |
10 #include "content/browser/speech/speech_recognition_engine.h" | 10 #include "content/browser/speech/speech_recognition_engine.h" |
11 #include "content/browser/speech/speech_recognizer_impl.h" | 11 #include "content/browser/speech/speech_recognizer_impl.h" |
12 #include "content/public/browser/browser_thread.h" | 12 #include "content/public/browser/browser_thread.h" |
13 #include "content/public/browser/content_browser_client.h" | 13 #include "content/public/browser/content_browser_client.h" |
14 #include "content/public/browser/resource_context.h" | 14 #include "content/public/browser/resource_context.h" |
15 #include "content/public/browser/speech_recognition_event_listener.h" | 15 #include "content/public/browser/speech_recognition_event_listener.h" |
16 #include "content/public/browser/speech_recognition_manager_delegate.h" | 16 #include "content/public/browser/speech_recognition_manager_delegate.h" |
17 #include "content/public/browser/speech_recognition_session_config.h" | 17 #include "content/public/browser/speech_recognition_session_config.h" |
18 #include "content/public/browser/speech_recognition_session_context.h" | 18 #include "content/public/browser/speech_recognition_session_context.h" |
19 #include "content/public/common/speech_recognition_result.h" | 19 #include "content/public/common/speech_recognition_result.h" |
20 #include "media/audio/audio_manager.h" | 20 #include "media/audio/audio_manager.h" |
21 | 21 |
22 using base::Callback; | 22 using base::Callback; |
23 using base::Unretained; | |
24 using content::BrowserMainLoop; | 23 using content::BrowserMainLoop; |
25 using content::BrowserThread; | 24 using content::BrowserThread; |
26 using content::SpeechRecognitionError; | 25 using content::SpeechRecognitionError; |
27 using content::SpeechRecognitionEventListener; | 26 using content::SpeechRecognitionEventListener; |
28 using content::SpeechRecognitionManager; | 27 using content::SpeechRecognitionManager; |
29 using content::SpeechRecognitionResult; | 28 using content::SpeechRecognitionResult; |
30 using content::SpeechRecognitionSessionContext; | 29 using content::SpeechRecognitionSessionContext; |
31 using content::SpeechRecognitionSessionConfig; | 30 using content::SpeechRecognitionSessionConfig; |
32 | 31 |
33 namespace content { | 32 namespace content { |
34 const int SpeechRecognitionManager::kSessionIDInvalid = 0; | 33 const int SpeechRecognitionManager::kSessionIDInvalid = 0; |
35 | 34 |
36 SpeechRecognitionManager* SpeechRecognitionManager::GetInstance() { | 35 SpeechRecognitionManager* SpeechRecognitionManager::GetInstance() { |
37 return speech::SpeechRecognitionManagerImpl::GetInstance(); | 36 return speech::SpeechRecognitionManagerImpl::GetInstance(); |
38 } | 37 } |
39 } // namespace content | 38 } // namespace content |
40 | 39 |
41 namespace { | 40 namespace { |
42 speech::SpeechRecognitionManagerImpl* g_speech_recognition_manager_impl; | 41 speech::SpeechRecognitionManagerImpl* g_speech_recognition_manager_impl; |
43 } // namespace | 42 } // namespace |
44 | 43 |
45 namespace speech { | 44 namespace speech { |
46 | 45 |
47 SpeechRecognitionManagerImpl* SpeechRecognitionManagerImpl::GetInstance() { | 46 SpeechRecognitionManagerImpl* SpeechRecognitionManagerImpl::GetInstance() { |
48 DCHECK(g_speech_recognition_manager_impl); | |
49 return g_speech_recognition_manager_impl; | 47 return g_speech_recognition_manager_impl; |
50 } | 48 } |
51 | 49 |
52 SpeechRecognitionManagerImpl::SpeechRecognitionManagerImpl() | 50 SpeechRecognitionManagerImpl::SpeechRecognitionManagerImpl() |
53 : session_id_capturing_audio_(kSessionIDInvalid), | 51 : session_id_capturing_audio_(kSessionIDInvalid), |
54 last_session_id_(kSessionIDInvalid), | 52 last_session_id_(kSessionIDInvalid), |
55 is_dispatching_event_(false), | 53 is_dispatching_event_(false), |
56 delegate_(content::GetContentClient()->browser()-> | 54 delegate_(content::GetContentClient()->browser()-> |
57 GetSpeechRecognitionManagerDelegate()) { | 55 GetSpeechRecognitionManagerDelegate()) { |
58 DCHECK(!g_speech_recognition_manager_impl); | 56 DCHECK(!g_speech_recognition_manager_impl); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 // If there is another active session, abort that. | 110 // If there is another active session, abort that. |
113 if (session_id_capturing_audio_ != kSessionIDInvalid && | 111 if (session_id_capturing_audio_ != kSessionIDInvalid && |
114 session_id_capturing_audio_ != session_id) { | 112 session_id_capturing_audio_ != session_id) { |
115 AbortSession(session_id_capturing_audio_); | 113 AbortSession(session_id_capturing_audio_); |
116 } | 114 } |
117 | 115 |
118 if (delegate_.get()) | 116 if (delegate_.get()) |
119 delegate_->CheckRecognitionIsAllowed( | 117 delegate_->CheckRecognitionIsAllowed( |
120 session_id, | 118 session_id, |
121 base::Bind(&SpeechRecognitionManagerImpl::RecognitionAllowedCallback, | 119 base::Bind(&SpeechRecognitionManagerImpl::RecognitionAllowedCallback, |
122 Unretained(this))); | 120 this->AsWeakPtr())); |
123 } | 121 } |
124 | 122 |
125 void SpeechRecognitionManagerImpl::RecognitionAllowedCallback(int session_id, | 123 void SpeechRecognitionManagerImpl::RecognitionAllowedCallback(int session_id, |
126 bool is_allowed) { | 124 bool is_allowed) { |
127 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 125 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
128 DCHECK(SessionExists(session_id)); | 126 DCHECK(SessionExists(session_id)); |
129 if (is_allowed) { | 127 if (is_allowed) { |
130 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 128 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
131 base::Bind(&SpeechRecognitionManagerImpl::DispatchEvent, | 129 base::Bind(&SpeechRecognitionManagerImpl::DispatchEvent, |
132 Unretained(this), session_id, EVENT_START)); | 130 this->AsWeakPtr(), session_id, EVENT_START)); |
133 } else { | 131 } else { |
134 sessions_.erase(session_id); | 132 sessions_.erase(session_id); |
135 } | 133 } |
136 } | 134 } |
137 | 135 |
138 void SpeechRecognitionManagerImpl::AbortSession(int session_id) { | 136 void SpeechRecognitionManagerImpl::AbortSession(int session_id) { |
139 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 137 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
140 if (!SessionExists(session_id)) | 138 if (!SessionExists(session_id)) |
141 return; | 139 return; |
142 | 140 |
143 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 141 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
144 base::Bind(&SpeechRecognitionManagerImpl::DispatchEvent, Unretained(this), | 142 base::Bind(&SpeechRecognitionManagerImpl::DispatchEvent, |
145 session_id, EVENT_ABORT)); | 143 this->AsWeakPtr(), session_id, EVENT_ABORT)); |
146 } | 144 } |
147 | 145 |
148 void SpeechRecognitionManagerImpl::StopAudioCaptureForSession(int session_id) { | 146 void SpeechRecognitionManagerImpl::StopAudioCaptureForSession(int session_id) { |
149 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 147 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
150 if (!SessionExists(session_id)) | 148 if (!SessionExists(session_id)) |
151 return; | 149 return; |
152 | 150 |
153 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 151 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
154 base::Bind(&SpeechRecognitionManagerImpl::DispatchEvent, Unretained(this), | 152 base::Bind(&SpeechRecognitionManagerImpl::DispatchEvent, |
155 session_id, EVENT_STOP_CAPTURE)); | 153 this->AsWeakPtr(), session_id, EVENT_STOP_CAPTURE)); |
156 } | 154 } |
157 | 155 |
158 // Here begins the SpeechRecognitionEventListener interface implementation, | 156 // Here begins the SpeechRecognitionEventListener interface implementation, |
159 // which will simply relay the events to the proper listener registered for the | 157 // which will simply relay the events to the proper listener registered for the |
160 // particular session (most likely InputTagSpeechDispatcherHost) and to the | 158 // particular session (most likely InputTagSpeechDispatcherHost) and to the |
161 // catch-all listener provided by the delegate (if any). | 159 // catch-all listener provided by the delegate (if any). |
162 | 160 |
163 void SpeechRecognitionManagerImpl::OnRecognitionStart(int session_id) { | 161 void SpeechRecognitionManagerImpl::OnRecognitionStart(int session_id) { |
164 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 162 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
165 if (!SessionExists(session_id)) | 163 if (!SessionExists(session_id)) |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
223 void SpeechRecognitionManagerImpl::OnAudioEnd(int session_id) { | 221 void SpeechRecognitionManagerImpl::OnAudioEnd(int session_id) { |
224 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 222 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
225 if (!SessionExists(session_id)) | 223 if (!SessionExists(session_id)) |
226 return; | 224 return; |
227 | 225 |
228 if (SpeechRecognitionEventListener* delegate_listener = GetDelegateListener()) | 226 if (SpeechRecognitionEventListener* delegate_listener = GetDelegateListener()) |
229 delegate_listener->OnAudioEnd(session_id); | 227 delegate_listener->OnAudioEnd(session_id); |
230 if (SpeechRecognitionEventListener* listener = GetListener(session_id)) | 228 if (SpeechRecognitionEventListener* listener = GetListener(session_id)) |
231 listener->OnAudioEnd(session_id); | 229 listener->OnAudioEnd(session_id); |
232 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 230 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
233 base::Bind(&SpeechRecognitionManagerImpl::DispatchEvent, Unretained(this), | 231 base::Bind(&SpeechRecognitionManagerImpl::DispatchEvent, |
234 session_id, EVENT_AUDIO_ENDED)); | 232 this->AsWeakPtr(), session_id, EVENT_AUDIO_ENDED)); |
235 } | 233 } |
236 | 234 |
237 void SpeechRecognitionManagerImpl::OnRecognitionResult( | 235 void SpeechRecognitionManagerImpl::OnRecognitionResult( |
238 int session_id, const content::SpeechRecognitionResult& result) { | 236 int session_id, const content::SpeechRecognitionResult& result) { |
239 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 237 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
240 if (!SessionExists(session_id)) | 238 if (!SessionExists(session_id)) |
241 return; | 239 return; |
242 | 240 |
243 if (SpeechRecognitionEventListener* delegate_listener = GetDelegateListener()) | 241 if (SpeechRecognitionEventListener* delegate_listener = GetDelegateListener()) |
244 delegate_listener->OnRecognitionResult(session_id, result); | 242 delegate_listener->OnRecognitionResult(session_id, result); |
(...skipping 28 matching lines...) Expand all Loading... |
273 void SpeechRecognitionManagerImpl::OnRecognitionEnd(int session_id) { | 271 void SpeechRecognitionManagerImpl::OnRecognitionEnd(int session_id) { |
274 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 272 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
275 if (!SessionExists(session_id)) | 273 if (!SessionExists(session_id)) |
276 return; | 274 return; |
277 | 275 |
278 if (SpeechRecognitionEventListener* delegate_listener = GetDelegateListener()) | 276 if (SpeechRecognitionEventListener* delegate_listener = GetDelegateListener()) |
279 delegate_listener->OnRecognitionEnd(session_id); | 277 delegate_listener->OnRecognitionEnd(session_id); |
280 if (SpeechRecognitionEventListener* listener = GetListener(session_id)) | 278 if (SpeechRecognitionEventListener* listener = GetListener(session_id)) |
281 listener->OnRecognitionEnd(session_id); | 279 listener->OnRecognitionEnd(session_id); |
282 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 280 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
283 base::Bind(&SpeechRecognitionManagerImpl::DispatchEvent, Unretained(this), | 281 base::Bind(&SpeechRecognitionManagerImpl::DispatchEvent, |
284 session_id, EVENT_RECOGNITION_ENDED)); | 282 this->AsWeakPtr(), session_id, EVENT_RECOGNITION_ENDED)); |
285 } | 283 } |
286 | 284 |
287 // TODO(primiano) After CL2: if we see that both InputTagDispatcherHost and | 285 // TODO(primiano) After CL2: if we see that both InputTagDispatcherHost and |
288 // SpeechRecognitionDispatcherHost do the same lookup operations, implement the | 286 // SpeechRecognitionDispatcherHost do the same lookup operations, implement the |
289 // lookup method directly here. | 287 // lookup method directly here. |
290 int SpeechRecognitionManagerImpl::LookupSessionByContext( | 288 int SpeechRecognitionManagerImpl::LookupSessionByContext( |
291 Callback<bool(const SpeechRecognitionSessionContext&)> matcher) const { | 289 Callback<bool(const SpeechRecognitionSessionContext&)> matcher) const { |
292 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 290 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
293 SessionsTable::const_iterator iter; | 291 SessionsTable::const_iterator iter; |
294 // Note: the callback (matcher) must NEVER perform non-const calls on us. | 292 // Note: the callback (matcher) must NEVER perform non-const calls on us. |
(...skipping 25 matching lines...) Expand all Loading... |
320 AbortSession(session.id); | 318 AbortSession(session.id); |
321 session.listener_is_active = false; | 319 session.listener_is_active = false; |
322 } | 320 } |
323 } | 321 } |
324 } | 322 } |
325 | 323 |
326 // ----------------------- Core FSM implementation --------------------------- | 324 // ----------------------- Core FSM implementation --------------------------- |
327 void SpeechRecognitionManagerImpl::DispatchEvent(int session_id, | 325 void SpeechRecognitionManagerImpl::DispatchEvent(int session_id, |
328 FSMEvent event) { | 326 FSMEvent event) { |
329 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 327 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 328 |
| 329 // There are some corner cases in which the session might be deleted (due to |
| 330 // an EndRecognition event) between a request (e.g. Abort) and its dispatch. |
| 331 if (!SessionExists(session_id)) |
| 332 return; |
| 333 |
330 const Session& session = GetSession(session_id); | 334 const Session& session = GetSession(session_id); |
331 FSMState session_state = GetSessionState(session_id); | 335 FSMState session_state = GetSessionState(session_id); |
332 DCHECK_LE(session_state, SESSION_STATE_MAX_VALUE); | 336 DCHECK_LE(session_state, SESSION_STATE_MAX_VALUE); |
333 DCHECK_LE(event, EVENT_MAX_VALUE); | 337 DCHECK_LE(event, EVENT_MAX_VALUE); |
334 | 338 |
335 // Event dispatching must be sequential, otherwise it will break all the rules | 339 // Event dispatching must be sequential, otherwise it will break all the rules |
336 // and the assumptions of the finite state automata model. | 340 // and the assumptions of the finite state automata model. |
337 DCHECK(!is_dispatching_event_); | 341 DCHECK(!is_dispatching_event_); |
338 is_dispatching_event_ = true; | 342 is_dispatching_event_ = true; |
339 ExecuteTransitionAndGetNextState(session, session_state, event); | 343 ExecuteTransitionAndGetNextState(session, session_state, event); |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
499 return BrowserMainLoop::GetAudioManager()->GetAudioInputDeviceModel(); | 503 return BrowserMainLoop::GetAudioManager()->GetAudioInputDeviceModel(); |
500 } | 504 } |
501 | 505 |
502 void SpeechRecognitionManagerImpl::ShowAudioInputSettings() { | 506 void SpeechRecognitionManagerImpl::ShowAudioInputSettings() { |
503 // Since AudioManager::ShowAudioInputSettings can potentially launch external | 507 // Since AudioManager::ShowAudioInputSettings can potentially launch external |
504 // processes, do that in the FILE thread to not block the calling threads. | 508 // processes, do that in the FILE thread to not block the calling threads. |
505 if (!BrowserThread::CurrentlyOn(BrowserThread::FILE)) { | 509 if (!BrowserThread::CurrentlyOn(BrowserThread::FILE)) { |
506 BrowserThread::PostTask( | 510 BrowserThread::PostTask( |
507 BrowserThread::FILE, FROM_HERE, | 511 BrowserThread::FILE, FROM_HERE, |
508 base::Bind(&SpeechRecognitionManagerImpl::ShowAudioInputSettings, | 512 base::Bind(&SpeechRecognitionManagerImpl::ShowAudioInputSettings, |
509 Unretained(this))); | 513 this->AsWeakPtr())); |
510 return; | 514 return; |
511 } | 515 } |
512 | 516 |
513 media::AudioManager* audio_manager = BrowserMainLoop::GetAudioManager(); | 517 media::AudioManager* audio_manager = BrowserMainLoop::GetAudioManager(); |
514 DCHECK(audio_manager->CanShowAudioInputSettings()); | 518 DCHECK(audio_manager->CanShowAudioInputSettings()); |
515 if (audio_manager->CanShowAudioInputSettings()) | 519 if (audio_manager->CanShowAudioInputSettings()) |
516 audio_manager->ShowAudioInputSettings(); | 520 audio_manager->ShowAudioInputSettings(); |
517 } | 521 } |
518 | 522 |
519 SpeechRecognitionManagerImpl::Session::Session() | 523 SpeechRecognitionManagerImpl::Session::Session() |
520 : id(kSessionIDInvalid), | 524 : id(kSessionIDInvalid), |
521 listener_is_active(true) { | 525 listener_is_active(true) { |
522 } | 526 } |
523 | 527 |
524 SpeechRecognitionManagerImpl::Session::~Session() { | 528 SpeechRecognitionManagerImpl::Session::~Session() { |
525 } | 529 } |
526 | 530 |
527 } // namespace speech | 531 } // namespace speech |
OLD | NEW |