Chromium Code Reviews| Index: chrome/browser/speech/speech_input_extension_manager.cc |
| diff --git a/chrome/browser/speech/speech_input_extension_manager.cc b/chrome/browser/speech/speech_input_extension_manager.cc |
| index 67ab90ce1a7fb4e0c9147a5f60caefd583f36d55..7f5da6b6ab6ac17f83a137954a68438a5de18175 100644 |
| --- a/chrome/browser/speech/speech_input_extension_manager.cc |
| +++ b/chrome/browser/speech/speech_input_extension_manager.cc |
| @@ -15,7 +15,6 @@ |
| #include "chrome/browser/profiles/profile_dependency_manager.h" |
| #include "chrome/browser/profiles/profile_keyed_service.h" |
| #include "chrome/browser/profiles/profile_keyed_service_factory.h" |
| -#include "chrome/browser/speech/speech_recognition_tray_icon_controller.h" |
| #include "chrome/common/chrome_notification_types.h" |
| #include "chrome/common/extensions/extension.h" |
| #include "chrome/common/pref_names.h" |
| @@ -23,9 +22,11 @@ |
| #include "content/public/browser/notification_registrar.h" |
| #include "content/public/browser/notification_service.h" |
| #include "content/public/browser/speech_recognition_manager.h" |
| -#include "content/public/browser/speech_recognizer.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 "net/url_request/url_request_context_getter.h" |
| using content::BrowserThread; |
| using content::SpeechRecognitionHypothesis; |
| @@ -55,12 +56,6 @@ const char kOnResultEvent[] = "experimental.speechInput.onResult"; |
| const char kOnSoundStartEvent[] = "experimental.speechInput.onSoundStart"; |
| const char kOnSoundEndEvent[] = "experimental.speechInput.onSoundEnd"; |
| -// Session id provided to the speech recognizer. Since only one extension can |
| -// be recording on the same time a constant value is enough as id. |
| -// TODO(primiano) this will not be valid anymore once speech input extension |
| -// will use the SpeechRecognitionManager and not the SpeechRecognizer directly. |
| -static const int kSpeechInputSessionId = 1; |
| - |
| // Wrap an SpeechInputExtensionManager using scoped_refptr to avoid |
| // assertion failures on destruction because of not using release(). |
| class SpeechInputExtensionManagerWrapper : public ProfileKeyedService { |
| @@ -157,7 +152,10 @@ SpeechInputExtensionManager::SpeechInputExtensionManager(Profile* profile) |
| : profile_(profile), |
| state_(kIdle), |
| registrar_(new content::NotificationRegistrar), |
| - speech_interface_(NULL) { |
| + speech_interface_(NULL), |
| + is_recognition_in_progress_(false), |
| + speech_recognition_session_id_( |
| + SpeechRecognitionManager::kSessionIDInvalid) { |
| registrar_->Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, |
| content::Source<Profile>(profile_)); |
| } |
| @@ -193,11 +191,14 @@ void SpeechInputExtensionManager::ShutdownOnUIThread() { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| VLOG(1) << "Profile shutting down."; |
| + BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| + base::Bind(&SpeechRecognitionManager::AbortAllSessionsForListener, |
| + base::Unretained(SpeechRecognitionManager::GetInstance()), |
| + base::Unretained(this))); |
| + |
| base::AutoLock auto_lock(state_lock_); |
| DCHECK(state_ != kShutdown); |
| if (state_ != kIdle) { |
| - DCHECK(notification_.get()); |
| - notification_->Hide(); |
| BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| base::Bind(&SpeechInputExtensionManager::ForceStopOnIOThread, this)); |
| } |
| @@ -244,7 +245,7 @@ void SpeechInputExtensionManager::OnRecognitionResult( |
| int session_id, |
| const content::SpeechRecognitionResult& result) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| - DCHECK_EQ(session_id, kSpeechInputSessionId); |
| + DCHECK_EQ(session_id, speech_recognition_session_id_); |
| // Stopping will start the disassociation with the extension. |
| // Make a copy to report the results to the proper one. |
| @@ -287,13 +288,13 @@ void SpeechInputExtensionManager::SetRecognitionResultOnUIThread( |
| } |
| void SpeechInputExtensionManager::OnRecognitionStart(int session_id) { |
| - DCHECK_EQ(session_id, kSpeechInputSessionId); |
| + DCHECK_EQ(session_id, speech_recognition_session_id_); |
| } |
| void SpeechInputExtensionManager::OnAudioStart(int session_id) { |
| VLOG(1) << "OnAudioStart"; |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| - DCHECK_EQ(session_id, kSpeechInputSessionId); |
| + DCHECK_EQ(session_id, speech_recognition_session_id_); |
| BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| base::Bind(&SpeechInputExtensionManager::DidStartReceivingAudioOnUIThread, |
| @@ -301,11 +302,16 @@ void SpeechInputExtensionManager::OnAudioStart(int session_id) { |
| } |
| void SpeechInputExtensionManager::OnAudioEnd(int session_id) { |
| - DCHECK_EQ(session_id, kSpeechInputSessionId); |
| } |
| void SpeechInputExtensionManager::OnRecognitionEnd(int session_id) { |
| - DCHECK_EQ(session_id, kSpeechInputSessionId); |
| + // In the very exceptional case in which we requested a new recognition before |
| + // the previous one ended, don't clobber the speech_recognition_session_id_. |
| + if (speech_recognition_session_id_ == session_id) { |
| + is_recognition_in_progress_ = false; |
| + speech_recognition_session_id_ = |
| + SpeechRecognitionManager::kSessionIDInvalid; |
| + } |
| } |
| void SpeechInputExtensionManager::DidStartReceivingAudioOnUIThread() { |
| @@ -319,21 +325,9 @@ void SpeechInputExtensionManager::DidStartReceivingAudioOnUIThread() { |
| VLOG(1) << "State changed to recording"; |
| state_ = kRecording; |
| - const Extension* extension = profile_->GetExtensionService()-> |
| - GetExtensionById(extension_id_in_use_, true); |
| - DCHECK(extension); |
| - |
| - bool show_notification = !profile_->GetPrefs()->GetBoolean( |
| - prefs::kSpeechInputTrayNotificationShown); |
| - |
| - if (!notification_.get()) |
| - notification_ = new SpeechRecognitionTrayIconController(); |
| - notification_->Show(UTF8ToUTF16(extension->name()), show_notification); |
| - |
| - if (show_notification) { |
| - profile_->GetPrefs()->SetBoolean( |
| - prefs::kSpeechInputTrayNotificationShown, true); |
| - } |
| + DCHECK(profile_); |
| + profile_->GetPrefs()->SetBoolean( |
| + prefs::kSpeechInputTrayNotificationShown, true); |
|
hans
2012/05/15 13:35:17
this looks like a simplification of the old code..
Primiano Tucci (use gerrit)
2012/05/16 10:16:00
The previous code was doing 3 things:
(a) checkin
|
| VLOG(1) << "Sending start notification"; |
| content::NotificationService::current()->Notify( |
| @@ -345,13 +339,13 @@ void SpeechInputExtensionManager::DidStartReceivingAudioOnUIThread() { |
| void SpeechInputExtensionManager::OnRecognitionError( |
| int session_id, const content::SpeechRecognitionError& error) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| - DCHECK_EQ(session_id, kSpeechInputSessionId); |
| // Simply return in case of an ERROR_ABORTED, since it is not contemplated |
| // in the speech input extensions architecture. |
| if (error.code == content::SPEECH_RECOGNITION_ERROR_ABORTED) |
| return; |
| + DCHECK_EQ(session_id, speech_recognition_session_id_); |
| VLOG(1) << "OnRecognitionError: " << error.code; |
| base::AutoLock auto_lock(state_lock_); |
| @@ -410,12 +404,12 @@ void SpeechInputExtensionManager::OnRecognitionError( |
| void SpeechInputExtensionManager::OnEnvironmentEstimationComplete( |
| int session_id) { |
| - DCHECK_EQ(session_id, kSpeechInputSessionId); |
| + DCHECK_EQ(session_id, speech_recognition_session_id_); |
| } |
| void SpeechInputExtensionManager::OnSoundStart(int session_id) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| - DCHECK_EQ(session_id, kSpeechInputSessionId); |
| + DCHECK_EQ(session_id, speech_recognition_session_id_); |
| VLOG(1) << "OnSoundStart"; |
| std::string json_args; |
| @@ -427,7 +421,6 @@ void SpeechInputExtensionManager::OnSoundStart(int session_id) { |
| void SpeechInputExtensionManager::OnSoundEnd(int session_id) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| - DCHECK_EQ(session_id, kSpeechInputSessionId); |
| VLOG(1) << "OnSoundEnd"; |
| std::string json_args; |
| @@ -470,11 +463,6 @@ void SpeechInputExtensionManager::DispatchError( |
| if (state_ == kShutdown) |
| return; |
| - if (state_ == kRecording) { |
| - DCHECK(notification_.get()); |
| - notification_->Hide(); |
| - } |
| - |
| extension_id = extension_id_in_use_; |
| ResetToIdleState(); |
| @@ -530,23 +518,37 @@ bool SpeechInputExtensionManager::Start( |
| NOTREACHED(); |
| } |
| + const Extension* extension = profile_->GetExtensionService()-> |
| + GetExtensionById(extension_id, true); |
| + DCHECK(extension); |
| + const string16& extension_name = UTF8ToUTF16(extension->name()); |
| + |
| extension_id_in_use_ = extension_id; |
| VLOG(1) << "State changed to starting"; |
| state_ = kStarting; |
| + // Checks if the security notification balloon has been already shown (only |
| + // once for a profile). It is reset on DidStartReceivingAudioOnUIThread. |
| + scoped_refptr<net::URLRequestContextGetter> url_request_context_getter = |
| + profile_->GetRequestContext(); |
| + const bool show_notification = !profile_->GetPrefs()->GetBoolean( |
| + prefs::kSpeechInputTrayNotificationShown); |
| + |
| BrowserThread::PostTask( |
| BrowserThread::IO, FROM_HERE, |
| base::Bind(&SpeechInputExtensionManager::StartOnIOThread, this, |
| - profile_->GetRequestContext(), language, grammar, |
| - filter_profanities)); |
| + url_request_context_getter, extension_name, language, grammar, |
| + filter_profanities, show_notification)); |
| return true; |
| } |
| void SpeechInputExtensionManager::StartOnIOThread( |
| - net::URLRequestContextGetter* context_getter, |
| + scoped_refptr<net::URLRequestContextGetter> context_getter, |
| + const string16& extension_name, |
| const std::string& language, |
| const std::string& grammar, |
| - bool filter_profanities) { |
| + bool filter_profanities, |
| + bool show_notification) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| VLOG(1) << "Requesting start (IO thread)"; |
| @@ -572,9 +574,13 @@ void SpeechInputExtensionManager::StartOnIOThread( |
| return; |
| } |
| - GetSpeechInputExtensionInterface()->StartRecording( |
| - this, context_getter, kSpeechInputSessionId, language, grammar, |
| - filter_profanities); |
| + GetSpeechInputExtensionInterface()->StartRecording(this, |
| + context_getter, |
| + extension_name, |
| + language, |
| + grammar, |
| + filter_profanities, |
| + show_notification); |
| } |
| bool SpeechInputExtensionManager::HasAudioInputDevices() { |
| @@ -617,20 +623,41 @@ void SpeechInputExtensionManager::IsRecordingOnUIThread( |
| void SpeechInputExtensionManager::StartRecording( |
| content::SpeechRecognitionEventListener* listener, |
| net::URLRequestContextGetter* context_getter, |
| - int session_id, |
| + const string16& extension_name, |
| const std::string& language, |
| const std::string& grammar, |
| - bool filter_profanities) { |
| + bool filter_profanities, |
| + bool show_notification) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| - DCHECK(!recognizer_); |
| - recognizer_ = content::SpeechRecognizer::Create( |
| - listener, session_id, language, grammar, context_getter, |
| - filter_profanities, "", ""); |
| - recognizer_->StartRecognition(); |
| + |
| + content::SpeechRecognitionSessionContext context; |
| + context.use_bubble_on_element = false; |
| + context.show_security_balloon = show_notification; |
| + context.context_name = extension_name; |
| + |
| + content::SpeechRecognitionSessionConfig config; |
| + // config.is_one_shot = true; // TODO(primiano) Uncomment when CL2.0 lands. |
| + config.language = language; |
| + config.grammar = grammar; |
| + config.initial_context = context; |
| + config.url_request_context_getter = context_getter; |
| + config.filter_profanities = filter_profanities; |
| + config.event_listener = listener; |
| + |
| + DCHECK(!is_recognition_in_progress_); |
| + SpeechRecognitionManager& manager = *SpeechRecognitionManager::GetInstance(); |
| + speech_recognition_session_id_ = |
| + manager.CreateSession(config); |
| + DCHECK_NE(speech_recognition_session_id_, |
| + SpeechRecognitionManager::kSessionIDInvalid); |
| + is_recognition_in_progress_ = true; |
| + manager.StartSession(speech_recognition_session_id_); |
| } |
| bool SpeechInputExtensionManager::HasValidRecognizer() { |
| - return !!recognizer_; |
| + if (!is_recognition_in_progress_) |
| + return false; |
| + return SpeechRecognitionManager::GetInstance()->IsCapturingAudio(); |
| } |
| bool SpeechInputExtensionManager::Stop(const std::string& extension_id, |
| @@ -691,13 +718,13 @@ void SpeechInputExtensionManager::ForceStopOnIOThread() { |
| } |
| void SpeechInputExtensionManager::StopRecording(bool recognition_failed) { |
| - if (recognizer_) { |
| - // Recognition is already cancelled in case of failure. |
| - // Double-cancelling leads to assertion failures. |
| - if (!recognition_failed) |
| - recognizer_->AbortRecognition(); |
| - recognizer_.release(); |
| - } |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + if (!is_recognition_in_progress_) |
| + return; |
| + DCHECK_NE(speech_recognition_session_id_, |
| + SpeechRecognitionManager::kSessionIDInvalid); |
| + SpeechRecognitionManager::GetInstance()->AbortSession( |
| + speech_recognition_session_id_); |
| } |
| void SpeechInputExtensionManager::StopSucceededOnUIThread() { |
| @@ -711,9 +738,6 @@ void SpeechInputExtensionManager::StopSucceededOnUIThread() { |
| std::string extension_id = extension_id_in_use_; |
| ResetToIdleState(); |
| - DCHECK(notification_.get()); |
| - notification_->Hide(); |
| - |
| content::NotificationService::current()->Notify( |
| chrome::NOTIFICATION_EXTENSION_SPEECH_INPUT_RECORDING_STOPPED, |
| // Guarded by the state_ == kShutdown check. |
| @@ -722,18 +746,5 @@ void SpeechInputExtensionManager::StopSucceededOnUIThread() { |
| } |
| void SpeechInputExtensionManager::OnAudioLevelsChange(int session_id, |
| - float volume, |
| - float noise_volume) { |
| - DCHECK_EQ(session_id, kSpeechInputSessionId); |
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| - base::Bind(&SpeechInputExtensionManager::SetInputVolumeOnUIThread, |
| - this, volume)); |
| -} |
| - |
| -void SpeechInputExtensionManager::SetInputVolumeOnUIThread( |
| - float volume) { |
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| - DCHECK(notification_.get()); |
| - notification_->SetVUMeterVolume(volume); |
| -} |
| + float volume, |
| + float noise_volume) {} |