Chromium Code Reviews| Index: content/browser/speech/speech_recognition_manager_impl.cc |
| diff --git a/content/browser/speech/speech_recognition_manager_impl.cc b/content/browser/speech/speech_recognition_manager_impl.cc |
| index 06b1d8809730482943747757297ee1fd8483cd04..25b4fe987feb2b1f839b03a4a24bb1b6886c7bc0 100644 |
| --- a/content/browser/speech/speech_recognition_manager_impl.cc |
| +++ b/content/browser/speech/speech_recognition_manager_impl.cc |
| @@ -6,6 +6,7 @@ |
| #include "base/bind.h" |
| #include "content/browser/browser_main_loop.h" |
| +#include "content/browser/renderer_host/media/media_stream_manager.h" |
| #include "content/browser/speech/google_one_shot_remote_engine.h" |
| #include "content/browser/speech/google_streaming_remote_engine.h" |
| #include "content/browser/speech/speech_recognition_engine.h" |
| @@ -17,13 +18,13 @@ |
| #include "content/public/browser/speech_recognition_manager_delegate.h" |
| #include "content/public/browser/speech_recognition_session_config.h" |
| #include "content/public/browser/speech_recognition_session_context.h" |
| +#include "content/public/common/speech_recognition_error.h" |
| #include "content/public/common/speech_recognition_result.h" |
| #include "media/audio/audio_manager.h" |
| using base::Callback; |
| using content::BrowserMainLoop; |
| using content::BrowserThread; |
| -using content::SpeechRecognitionError; |
| using content::SpeechRecognitionEventListener; |
| using content::SpeechRecognitionManager; |
| using content::SpeechRecognitionResult; |
| @@ -50,12 +51,86 @@ void ShowAudioInputSettingsOnFileThread() { |
| namespace speech { |
| +class SpeechRecognitionManagerImpl::PermissionRequest |
| + : public media_stream::MediaStreamRequester { |
| + public: |
| + PermissionRequest(int session_id, |
| + const base::Callback<void(bool is_allowed)>& callback) |
| + : session_id_(session_id), |
| + callback_(callback), |
| + started_(false) { |
| + } |
| + |
| + virtual ~PermissionRequest() { |
| + if (started_) |
| + Abort(); |
| + } |
| + |
| + void Start(int render_process_id, int render_view_id, const GURL& origin) { |
|
no longer working on chromium
2012/09/13 15:11:02
add thread DCheck here.
hans
2012/09/13 15:15:52
Done.
|
| + started_ = true; |
| + BrowserMainLoop::GetMediaStreamManager()->GenerateStream( |
| + this, |
| + render_process_id, |
| + render_view_id, |
| + media_stream::StreamOptions(/*audio=*/true, /*video=*/false), |
| + origin, |
| + &label_); |
| + } |
| + |
| + void Abort() { |
|
no longer working on chromium
2012/09/13 15:11:02
ditto
hans
2012/09/13 15:15:52
Done.
|
| + started_ = false; |
| + BrowserMainLoop::GetMediaStreamManager()->CancelGenerateStream(label_); |
| + } |
| + |
| + int Session() const { return session_id_; } |
| + |
| + // MediaStreamRequester methods. |
| + virtual void StreamGenerated( |
| + const std::string& label, |
| + const media_stream::StreamDeviceInfoArray& audio_devices, |
| + const media_stream::StreamDeviceInfoArray& video_devices) OVERRIDE { |
| + // TODO(hans): One day it would be nice to actually use the generated stream |
| + // but right now we only use it to request permission, and then we dump it. |
| + started_ = false; |
|
no longer working on chromium
2012/09/13 15:11:02
ditto
hans
2012/09/13 15:15:52
Done.
|
| + BrowserThread::PostTask( |
| + BrowserThread::IO, |
| + FROM_HERE, |
| + base::Bind(&media_stream::MediaStreamManager::StopGeneratedStream, |
| + base::Unretained(BrowserMainLoop::GetMediaStreamManager()), |
| + label)); |
| + callback_.Run(true); |
| + } |
| + |
| + virtual void StreamGenerationFailed(const std::string& label) OVERRIDE { |
| + started_ = false; |
|
no longer working on chromium
2012/09/13 15:11:02
ditto
hans
2012/09/13 15:15:52
Done.
|
| + callback_.Run(false); |
| + } |
| + |
| + // The callbacks below are ignored. |
| + virtual void AudioDeviceFailed(const std::string& label, |
| + int index) OVERRIDE {} |
| + virtual void VideoDeviceFailed(const std::string& label, |
| + int index) OVERRIDE {} |
| + virtual void DevicesEnumerated( |
| + const std::string& label, |
| + const media_stream::StreamDeviceInfoArray& devices) OVERRIDE {} |
| + virtual void DeviceOpened( |
| + const std::string& label, |
| + const media_stream::StreamDeviceInfo& device_info) OVERRIDE {} |
| + |
| + private: |
| + int session_id_; |
| + base::Callback<void(bool is_allowed)> callback_; |
| + std::string label_; |
| + bool started_; |
| +}; |
| + |
| SpeechRecognitionManagerImpl* SpeechRecognitionManagerImpl::GetInstance() { |
| return g_speech_recognition_manager_impl; |
| } |
| SpeechRecognitionManagerImpl::SpeechRecognitionManagerImpl() |
| - : session_id_capturing_audio_(kSessionIDInvalid), |
| + : primary_session_id_(kSessionIDInvalid), |
| last_session_id_(kSessionIDInvalid), |
| is_dispatching_event_(false), |
| delegate_(content::GetContentClient()->browser()-> |
| @@ -124,28 +199,59 @@ void SpeechRecognitionManagerImpl::StartSession(int session_id) { |
| return; |
| // If there is another active session, abort that. |
| - if (session_id_capturing_audio_ != kSessionIDInvalid && |
| - session_id_capturing_audio_ != session_id) { |
| - AbortSession(session_id_capturing_audio_); |
| + if (primary_session_id_ != kSessionIDInvalid && |
| + primary_session_id_ != session_id) { |
| + AbortSession(primary_session_id_); |
| } |
| - if (delegate_.get()) |
| + primary_session_id_ = session_id; |
| + |
| + if (delegate_.get()) { |
| delegate_->CheckRecognitionIsAllowed( |
| session_id, |
| base::Bind(&SpeechRecognitionManagerImpl::RecognitionAllowedCallback, |
| - weak_factory_.GetWeakPtr())); |
| + weak_factory_.GetWeakPtr(), |
| + session_id)); |
| + } |
| } |
| void SpeechRecognitionManagerImpl::RecognitionAllowedCallback(int session_id, |
| + bool ask_user, |
| bool is_allowed) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| - DCHECK(SessionExists(session_id)); |
| + if (!SessionExists(session_id)) |
| + return; |
| + |
| + if (ask_user) { |
| + const SpeechRecognitionSessionContext& context = |
| + GetSessionContext(session_id); |
| + |
| + permission_request_.reset(new PermissionRequest( |
| + session_id, |
| + base::Bind(&SpeechRecognitionManagerImpl::RecognitionAllowedCallback, |
| + weak_factory_.GetWeakPtr(), |
| + session_id, |
| + false))); |
| + |
| + permission_request_->Start(context.render_process_id, |
| + context.render_view_id, |
| + GURL(context.context_name)); |
| + |
| + return; |
| + } |
| + |
| + permission_request_.reset(); |
| + |
| if (is_allowed) { |
| MessageLoop::current()->PostTask(FROM_HERE, |
| base::Bind(&SpeechRecognitionManagerImpl::DispatchEvent, |
| weak_factory_.GetWeakPtr(), session_id, EVENT_START)); |
| } else { |
| - sessions_.erase(session_id); |
| + OnRecognitionError(session_id, content::SpeechRecognitionError( |
| + content::SPEECH_RECOGNITION_ERROR_NOT_ALLOWED)); |
| + MessageLoop::current()->PostTask(FROM_HERE, |
| + base::Bind(&SpeechRecognitionManagerImpl::DispatchEvent, |
| + weak_factory_.GetWeakPtr(), session_id, EVENT_ABORT)); |
| } |
| } |
| @@ -154,6 +260,12 @@ void SpeechRecognitionManagerImpl::AbortSession(int session_id) { |
| if (!SessionExists(session_id)) |
| return; |
| + if (permission_request_.get() && |
| + permission_request_->Session() == session_id) { |
| + DCHECK(permission_request_.get()); |
| + permission_request_->Abort(); |
| + } |
| + |
| MessageLoop::current()->PostTask(FROM_HERE, |
| base::Bind(&SpeechRecognitionManagerImpl::DispatchEvent, |
| weak_factory_.GetWeakPtr(), session_id, EVENT_ABORT)); |
| @@ -164,6 +276,12 @@ void SpeechRecognitionManagerImpl::StopAudioCaptureForSession(int session_id) { |
| if (!SessionExists(session_id)) |
| return; |
| + if (permission_request_.get() && |
| + permission_request_->Session() == session_id) { |
| + DCHECK(permission_request_.get()); |
| + permission_request_->Abort(); |
| + } |
| + |
| MessageLoop::current()->PostTask(FROM_HERE, |
| base::Bind(&SpeechRecognitionManagerImpl::DispatchEvent, |
| weak_factory_.GetWeakPtr(), session_id, EVENT_STOP_CAPTURE)); |
| @@ -179,7 +297,7 @@ void SpeechRecognitionManagerImpl::OnRecognitionStart(int session_id) { |
| if (!SessionExists(session_id)) |
| return; |
| - DCHECK_EQ(session_id_capturing_audio_, session_id); |
| + DCHECK_EQ(primary_session_id_, session_id); |
| if (SpeechRecognitionEventListener* delegate_listener = GetDelegateListener()) |
| delegate_listener->OnRecognitionStart(session_id); |
| if (SpeechRecognitionEventListener* listener = GetListener(session_id)) |
| @@ -191,7 +309,7 @@ void SpeechRecognitionManagerImpl::OnAudioStart(int session_id) { |
| if (!SessionExists(session_id)) |
| return; |
| - DCHECK_EQ(session_id_capturing_audio_, session_id); |
| + DCHECK_EQ(primary_session_id_, session_id); |
| if (SpeechRecognitionEventListener* delegate_listener = GetDelegateListener()) |
| delegate_listener->OnAudioStart(session_id); |
| if (SpeechRecognitionEventListener* listener = GetListener(session_id)) |
| @@ -204,7 +322,7 @@ void SpeechRecognitionManagerImpl::OnEnvironmentEstimationComplete( |
| if (!SessionExists(session_id)) |
| return; |
| - DCHECK_EQ(session_id_capturing_audio_, session_id); |
| + DCHECK_EQ(primary_session_id_, session_id); |
| if (SpeechRecognitionEventListener* delegate_listener = GetDelegateListener()) |
| delegate_listener->OnEnvironmentEstimationComplete(session_id); |
| if (SpeechRecognitionEventListener* listener = GetListener(session_id)) |
| @@ -216,7 +334,7 @@ void SpeechRecognitionManagerImpl::OnSoundStart(int session_id) { |
| if (!SessionExists(session_id)) |
| return; |
| - DCHECK_EQ(session_id_capturing_audio_, session_id); |
| + DCHECK_EQ(primary_session_id_, session_id); |
| if (SpeechRecognitionEventListener* delegate_listener = GetDelegateListener()) |
| delegate_listener->OnSoundStart(session_id); |
| if (SpeechRecognitionEventListener* listener = GetListener(session_id)) |
| @@ -396,9 +514,11 @@ void SpeechRecognitionManagerImpl::ExecuteTransitionAndGetNextState( |
| case EVENT_START: |
| return SessionStart(session); |
| case EVENT_ABORT: |
| + return SessionAbort(session); |
| case EVENT_RECOGNITION_ENDED: |
| return SessionDelete(session); |
| case EVENT_STOP_CAPTURE: |
| + return SessionStopAudioCapture(session); |
| case EVENT_AUDIO_ENDED: |
| return; |
| } |
| @@ -448,33 +568,33 @@ SpeechRecognitionManagerImpl::GetSessionState(int session_id) const { |
| // - Are guaranteed to be not reentrant (themselves and each other); |
| void SpeechRecognitionManagerImpl::SessionStart(const Session& session) { |
| - session_id_capturing_audio_ = session.id; |
| + DCHECK_EQ(primary_session_id_, session.id); |
| session.recognizer->StartRecognition(); |
| } |
| void SpeechRecognitionManagerImpl::SessionAbort(const Session& session) { |
| - if (session_id_capturing_audio_ == session.id) |
| - session_id_capturing_audio_ = kSessionIDInvalid; |
| - DCHECK(session.recognizer.get() && session.recognizer->IsActive()); |
| + if (primary_session_id_ == session.id) |
| + primary_session_id_ = kSessionIDInvalid; |
| + DCHECK(session.recognizer.get()); |
| session.recognizer->AbortRecognition(); |
| } |
| void SpeechRecognitionManagerImpl::SessionStopAudioCapture( |
| const Session& session) { |
| - DCHECK(session.recognizer.get() && session.recognizer->IsCapturingAudio()); |
| + DCHECK(session.recognizer.get()); |
| session.recognizer->StopAudioCapture(); |
| } |
| void SpeechRecognitionManagerImpl::ResetCapturingSessionId( |
| const Session& session) { |
| - DCHECK_EQ(session_id_capturing_audio_, session.id); |
| - session_id_capturing_audio_ = kSessionIDInvalid; |
| + DCHECK_EQ(primary_session_id_, session.id); |
| + primary_session_id_ = kSessionIDInvalid; |
| } |
| void SpeechRecognitionManagerImpl::SessionDelete(const Session& session) { |
| DCHECK(session.recognizer == NULL || !session.recognizer->IsActive()); |
| - if (session_id_capturing_audio_ == session.id) |
| - session_id_capturing_audio_ = kSessionIDInvalid; |
| + if (primary_session_id_ == session.id) |
| + primary_session_id_ = kSessionIDInvalid; |
| sessions_.erase(session.id); |
| } |