Chromium Code Reviews| Index: chrome/browser/speech/chrome_speech_recognition_manager_delegate.cc |
| diff --git a/chrome/browser/speech/chrome_speech_recognition_manager_delegate.cc b/chrome/browser/speech/chrome_speech_recognition_manager_delegate.cc |
| index f22f95541e0bd6f6ef1382511134b637126e3a2c..81b1c7fdfbeed03d1fb601106edf06054c169de6 100644 |
| --- a/chrome/browser/speech/chrome_speech_recognition_manager_delegate.cc |
| +++ b/chrome/browser/speech/chrome_speech_recognition_manager_delegate.cc |
| @@ -16,6 +16,7 @@ |
| #include "chrome/browser/profiles/profile_manager.h" |
| #include "chrome/browser/speech/chrome_speech_recognition_preferences.h" |
| #include "chrome/browser/speech/speech_recognition_tray_icon_controller.h" |
| +#include "chrome/browser/speech/tab_watcher.h" |
| #include "chrome/browser/tab_contents/tab_util.h" |
| #include "chrome/browser/view_type_utils.h" |
| #include "chrome/common/pref_names.h" |
| @@ -39,12 +40,9 @@ |
| using content::BrowserThread; |
| using content::SpeechRecognitionManager; |
| -using content::SpeechRecognitionSessionContext; |
| using content::WebContents; |
| namespace { |
| -const int kNoActiveBubble = |
| - content::SpeechRecognitionManager::kSessionIDInvalid; |
| const char kExtensionPrefix[] = "chrome-extension://"; |
| @@ -124,38 +122,33 @@ class ChromeSpeechRecognitionManagerDelegate::OptionalRequestInfo |
| }; |
| ChromeSpeechRecognitionManagerDelegate::ChromeSpeechRecognitionManagerDelegate() |
| - : active_bubble_session_id_(kNoActiveBubble) { |
| +{ |
|
Satish
2012/07/03 15:11:57
move to previous line
Primiano Tucci (use gerrit)
2012/07/03 16:54:35
It will overflow the row. Chrome....Delegate() tak
Satish
2012/07/04 09:52:51
In such cases we write it as
ChromeSpeechRecogniti
Primiano Tucci (use gerrit)
2012/07/04 11:18:15
Done.
|
| } |
| ChromeSpeechRecognitionManagerDelegate:: |
| ~ChromeSpeechRecognitionManagerDelegate() { |
|
Satish
2012/07/03 15:11:57
could move to previous line
Primiano Tucci (use gerrit)
2012/07/03 16:54:35
As above, overflows 80 cols.
Satish
2012/07/04 09:52:51
Ok, no 4 space indentation then
Primiano Tucci (use gerrit)
2012/07/04 11:18:15
Done.
|
| if (tray_icon_controller_.get()) |
| tray_icon_controller_->Hide(); |
| - if (active_bubble_session_id_ != kNoActiveBubble) { |
| - DCHECK(bubble_controller_.get()); |
| - bubble_controller_->CloseBubble(active_bubble_session_id_); |
| - } |
| + if (bubble_controller_.get() && bubble_controller_->GetActiveSessionID()) |
|
Satish
2012/07/03 15:11:57
can the second check be moved inside CloseBubble()
Primiano Tucci (use gerrit)
2012/07/03 16:54:35
Well, the check wasn't needed. Removed.
|
| + bubble_controller_->CloseBubble(); |
| } |
| void ChromeSpeechRecognitionManagerDelegate::InfoBubbleButtonClicked( |
| int session_id, SpeechRecognitionBubble::Button button) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| - DCHECK_EQ(active_bubble_session_id_, session_id); |
| // Note, the session might have been destroyed, therefore avoid calls to the |
| // manager which imply its existance (e.g., GetSessionContext()). |
| if (button == SpeechRecognitionBubble::BUTTON_CANCEL) { |
| - GetBubbleController()->CloseBubble(session_id); |
| + GetBubbleController()->CloseBubble(); |
| last_session_config_.reset(); |
| - active_bubble_session_id_ = kNoActiveBubble; |
| // We can safely call AbortSession even if the session has already ended, |
| // the manager's public methods are reliable and will handle it properly. |
| SpeechRecognitionManager::GetInstance()->AbortSession(session_id); |
| } else if (button == SpeechRecognitionBubble::BUTTON_TRY_AGAIN) { |
| - GetBubbleController()->CloseBubble(session_id); |
| - active_bubble_session_id_ = kNoActiveBubble; |
| + GetBubbleController()->CloseBubble(); |
| RestartLastSession(); |
| } |
|
Satish
2012/07/03 15:11:57
if the above are the only 2 possible values for |b
Primiano Tucci (use gerrit)
2012/07/03 16:54:35
Done.
|
| } |
| @@ -163,14 +156,18 @@ void ChromeSpeechRecognitionManagerDelegate::InfoBubbleButtonClicked( |
| void ChromeSpeechRecognitionManagerDelegate::InfoBubbleFocusChanged( |
| int session_id) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| - DCHECK_EQ(active_bubble_session_id_, session_id); |
| + |
| + // This check is needed since on some systems (MacOS), in rare cases, if the |
| + // user clicks repeatedly and fast on the input element, the FocusChanged |
| + // event (corresponding to the old session that should be aborted) can be |
| + // received after a new session (corresponding to the 2nd click) is started. |
| + if (GetBubbleController()->GetActiveSessionID() != session_id) |
|
Satish
2012/07/03 15:11:57
If you ignore the focus change event for the first
Primiano Tucci (use gerrit)
2012/07/03 16:54:35
Yes, even if the UI events are received out of ord
|
| + return; |
| // Note, the session might have been destroyed, therefore avoid calls to the |
| // manager which imply its existance (e.g., GetSessionContext()). |
| - |
| - GetBubbleController()->CloseBubble(session_id); |
| + GetBubbleController()->CloseBubble(); |
| last_session_config_.reset(); |
| - active_bubble_session_id_ = kNoActiveBubble; |
| // If the user clicks outside the bubble while capturing audio we abort the |
| // session. Otherwise, i.e. audio capture is ended and we are just waiting for |
| @@ -183,11 +180,25 @@ void ChromeSpeechRecognitionManagerDelegate::RestartLastSession() { |
| DCHECK(last_session_config_.get()); |
| SpeechRecognitionManager* manager = SpeechRecognitionManager::GetInstance(); |
| const int new_session_id = manager->CreateSession(*last_session_config_); |
| - DCHECK_NE(new_session_id, kNoActiveBubble); |
| + DCHECK_NE(SpeechRecognitionManager::kSessionIDInvalid, new_session_id); |
| last_session_config_.reset(); |
| manager->StartSession(new_session_id); |
| } |
| +void ChromeSpeechRecognitionManagerDelegate::TabClosedCallback( |
| + int render_process_id, int render_view_id) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + |
| + if (SpeechRecognitionManager* mgr = SpeechRecognitionManager::GetInstance()) |
|
Satish
2012/07/03 15:11:57
mgr -> manager
Primiano Tucci (use gerrit)
2012/07/03 16:54:35
Done.
|
| + mgr->AbortAllSessionsForRenderer(render_process_id, render_view_id); |
| + |
| + if (bubble_controller_.get() && |
| + bubble_controller_->IsShowingBubbleOn(render_process_id, |
|
Satish
2012/07/03 15:11:57
looks like bubble controller holds the current ren
Primiano Tucci (use gerrit)
2012/07/03 16:54:35
Hmm similar to the offline discussion about active
|
| + render_view_id)) { |
| + bubble_controller_->CloseBubble(); |
| + } |
| +} |
| + |
| void ChromeSpeechRecognitionManagerDelegate::OnRecognitionStart( |
| int session_id) { |
| const content::SpeechRecognitionSessionContext& context = |
| @@ -199,21 +210,27 @@ void ChromeSpeechRecognitionManagerDelegate::OnRecognitionStart( |
| SpeechRecognitionManager::GetInstance()->GetSessionConfig(session_id))); |
| // Create and show the bubble. |
| - DCHECK_EQ(active_bubble_session_id_, kNoActiveBubble); |
| - active_bubble_session_id_ = session_id; |
| GetBubbleController()->CreateBubble(session_id, |
| context.render_process_id, |
| context.render_view_id, |
| context.element_rect); |
| + } |
| - // TODO(primiano) Why not creating directly the bubble in warmup mode? |
| - GetBubbleController()->SetBubbleWarmUpMode(session_id); |
| + // Register callback to auto abort session on tab closure. |
| + // |tab_watcher_| is lazyly istantiated on the first call. |
| + if (!tab_watcher_.get()) { |
| + tab_watcher_ = new TabWatcher( |
| + base::Bind(&ChromeSpeechRecognitionManagerDelegate::TabClosedCallback, |
| + base::Unretained(this)), |
| + BrowserThread::IO); |
| } |
| + tab_watcher_->Watch(context.render_process_id, context.render_view_id); |
|
Satish
2012/07/03 15:11:57
can you also stop observing the tab when the bubbl
Primiano Tucci (use gerrit)
2012/07/03 16:54:35
I thought about that but it means that in such cas
Satish
2012/07/04 09:52:51
If the user had 20 tabs open and used speech recog
Primiano Tucci (use gerrit)
2012/07/04 11:18:15
Events are pre-filtered by the notification servic
|
| } |
| void ChromeSpeechRecognitionManagerDelegate::OnAudioStart(int session_id) { |
| if (RequiresBubble(session_id)) { |
| - GetBubbleController()->SetBubbleRecordingMode(session_id); |
| + DCHECK_EQ(session_id, GetBubbleController()->GetActiveSessionID()); |
|
Satish
2012/07/03 15:11:57
It doesn't feel right to ask the bubble controller
Primiano Tucci (use gerrit)
2012/07/03 16:54:35
As discussed offline, it doesn't look pretty nice,
|
| + GetBubbleController()->SetBubbleRecordingMode(); |
| } else if (RequiresTrayIcon(session_id)) { |
| // We post the action to the UI thread for sessions requiring a tray icon, |
| // since ChromeSpeechRecognitionPreferences (which requires UI thread) is |
| @@ -242,8 +259,9 @@ void ChromeSpeechRecognitionManagerDelegate::OnSoundEnd(int session_id) { |
| void ChromeSpeechRecognitionManagerDelegate::OnAudioEnd(int session_id) { |
| // OnAudioEnd can be also raised after an abort, when the bubble has already |
| // been closed. |
| - if (RequiresBubble(session_id) && active_bubble_session_id_ == session_id) { |
| - GetBubbleController()->SetBubbleRecognizingMode(session_id); |
| + if (GetBubbleController()->GetActiveSessionID() == session_id) { |
|
Satish
2012/07/03 15:11:57
why is this condition different from what you have
Primiano Tucci (use gerrit)
2012/07/03 16:54:35
In the AudioStart event, in the case that that par
|
| + DCHECK(RequiresBubble(session_id)); |
| + GetBubbleController()->SetBubbleRecognizingMode(); |
| } else if (RequiresTrayIcon(session_id)) { |
| GetTrayIconController()->Hide(); |
| } |
| @@ -251,19 +269,13 @@ void ChromeSpeechRecognitionManagerDelegate::OnAudioEnd(int session_id) { |
| void ChromeSpeechRecognitionManagerDelegate::OnRecognitionResult( |
| int session_id, const content::SpeechRecognitionResult& result) { |
| - // A result can be dispatched when the bubble is not visible anymore (e.g., |
| - // lost focus while waiting for a result, thus continuing in background). |
| - if (RequiresBubble(session_id) && active_bubble_session_id_ == session_id) { |
| - GetBubbleController()->CloseBubble(session_id); |
| - last_session_config_.reset(); |
| - active_bubble_session_id_ = kNoActiveBubble; |
| - } |
| + // The bubble will be closed upon the OnEnd event, which will follow soon. |
| } |
| void ChromeSpeechRecognitionManagerDelegate::OnRecognitionError( |
| int session_id, const content::SpeechRecognitionError& error) { |
| // An error can be dispatched when the bubble is not visible anymore. |
| - if (active_bubble_session_id_ != session_id) |
| + if (GetBubbleController()->GetActiveSessionID() != session_id) |
| return; |
| DCHECK(RequiresBubble(session_id)); |
| @@ -299,28 +311,29 @@ void ChromeSpeechRecognitionManagerDelegate::OnRecognitionError( |
| return; |
| } |
| GetBubbleController()->SetBubbleMessage( |
| - session_id, l10n_util::GetStringUTF16(error_message_id)); |
| + l10n_util::GetStringUTF16(error_message_id)); |
| } |
| void ChromeSpeechRecognitionManagerDelegate::OnAudioLevelsChange( |
| int session_id, float volume, float noise_volume) { |
| - if (active_bubble_session_id_ == session_id) { |
| + if (GetBubbleController()->GetActiveSessionID() == session_id) { |
| DCHECK(RequiresBubble(session_id)); |
| - GetBubbleController()->SetBubbleInputVolume(session_id, |
| - volume, noise_volume); |
| + GetBubbleController()->SetBubbleInputVolume(volume, noise_volume); |
| } else if (RequiresTrayIcon(session_id)) { |
| GetTrayIconController()->SetVUMeterVolume(volume); |
| } |
| } |
| void ChromeSpeechRecognitionManagerDelegate::OnRecognitionEnd(int session_id) { |
| - // No need to remove the bubble here, since either one of the following events |
| - // must have happened prior to this callback: |
| - // - A previous OnRecognitionResult event already closed the bubble. |
| - // - An error occurred, so the bubble is showing the error and will be closed |
| - // when it will lose focus (by InfoBubbleFocusChanged()). |
| - // - The bubble lost focus or the user pressed the Cancel button, thus it has |
| - // been closed by InfoBubbleFocusChanged(), which triggered an AbortSession. |
| + // The only case in which the OnRecognitionEnd should not close the bubble is |
| + // when we are showing an error. In this case the bubble will be closed by |
| + // the |InfoBubbleFocusChanged| method, when the users clicks either the |
| + // "Cancel" button or outside of the bubble. |
| + if (GetBubbleController()->GetActiveSessionID() == session_id && |
| + !GetBubbleController()->IsShowingMessage()) { |
| + DCHECK(RequiresBubble(session_id)); |
| + GetBubbleController()->CloseBubble(); |
| + } |
| } |
| void ChromeSpeechRecognitionManagerDelegate::GetDiagnosticInformation( |