Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(135)

Unified Diff: chrome/browser/speech/chrome_speech_recognition_manager_delegate.cc

Issue 10663018: Changing tab closure handling logic in speech recognition code and cleaning bubble controller. (Spe… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Relaxed thread checks for tests. Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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..7bdb8ec7c6c079e82739b6112090a83aa24d9046 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,53 +122,54 @@ class ChromeSpeechRecognitionManagerDelegate::OptionalRequestInfo
};
ChromeSpeechRecognitionManagerDelegate::ChromeSpeechRecognitionManagerDelegate()
- : active_bubble_session_id_(kNoActiveBubble) {
+{
}
ChromeSpeechRecognitionManagerDelegate::
~ChromeSpeechRecognitionManagerDelegate() {
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_->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();
+ } else {
+ NOTREACHED();
}
}
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)
+ 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 +182,27 @@ 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* manager =
+ SpeechRecognitionManager::GetInstance()) {
+ manager->AbortAllSessionsForRenderer(render_process_id, render_view_id);
+ }
+
+ if (bubble_controller_.get() &&
+ bubble_controller_->IsShowingBubbleOn(render_process_id,
+ render_view_id)) {
+ bubble_controller_->CloseBubble();
+ }
+}
+
void ChromeSpeechRecognitionManagerDelegate::OnRecognitionStart(
int session_id) {
const content::SpeechRecognitionSessionContext& context =
@@ -199,21 +214,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);
}
void ChromeSpeechRecognitionManagerDelegate::OnAudioStart(int session_id) {
if (RequiresBubble(session_id)) {
- GetBubbleController()->SetBubbleRecordingMode(session_id);
+ DCHECK_EQ(session_id, GetBubbleController()->GetActiveSessionID());
+ 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 +263,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) {
+ DCHECK(RequiresBubble(session_id));
+ GetBubbleController()->SetBubbleRecognizingMode();
} else if (RequiresTrayIcon(session_id)) {
GetTrayIconController()->Hide();
}
@@ -251,19 +273,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 +315,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(

Powered by Google App Engine
This is Rietveld 408576698