| 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 6b0162c685cfaab441316b65a7d306d4bdb24ea5..b771ac744b6b8dc03fc48d4e21545fd75db60823 100644
|
| --- a/chrome/browser/speech/chrome_speech_recognition_manager_delegate.cc
|
| +++ b/chrome/browser/speech/chrome_speech_recognition_manager_delegate.cc
|
| @@ -13,6 +13,7 @@
|
| #include "chrome/browser/browser_process.h"
|
| #include "chrome/browser/prefs/pref_service.h"
|
| #include "chrome/browser/profiles/profile_manager.h"
|
| +#include "chrome/browser/speech/speech_recognition_tray_icon_controller.h"
|
| #include "chrome/browser/tab_contents/tab_util.h"
|
| #include "chrome/browser/view_type_utils.h"
|
| #include "chrome/common/pref_names.h"
|
| @@ -36,10 +37,20 @@
|
| using content::BrowserThread;
|
| using content::SpeechRecognitionManager;
|
| using content::WebContents;
|
| +using content::SpeechRecognitionSessionContext;
|
|
|
| namespace {
|
| const int kNoActiveBubble =
|
| content::SpeechRecognitionManager::kSessionIDInvalid;
|
| +
|
| +bool RequiresBubble(int session_id) {
|
| + return SpeechRecognitionManager::GetInstance()->
|
| + GetSessionContext(session_id).requested_by_page_element;
|
| +}
|
| +
|
| +bool RequiresTrayIcon(int session_id) {
|
| + return !RequiresBubble(session_id);
|
| +}
|
| } // namespace
|
|
|
| namespace speech {
|
| @@ -108,13 +119,17 @@ class ChromeSpeechRecognitionManagerDelegate::OptionalRequestInfo
|
| };
|
|
|
| ChromeSpeechRecognitionManagerDelegate::ChromeSpeechRecognitionManagerDelegate()
|
| - : bubble_controller_(new SpeechRecognitionBubbleController(
|
| - ALLOW_THIS_IN_INITIALIZER_LIST(this))),
|
| - active_bubble_session_id_(kNoActiveBubble) {
|
| + : 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_);
|
| + }
|
| }
|
|
|
| void ChromeSpeechRecognitionManagerDelegate::InfoBubbleButtonClicked(
|
| @@ -122,8 +137,11 @@ void ChromeSpeechRecognitionManagerDelegate::InfoBubbleButtonClicked(
|
| 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) {
|
| - bubble_controller_->CloseBubble(session_id);
|
| + GetBubbleController()->CloseBubble(session_id);
|
| last_session_config_.reset();
|
| active_bubble_session_id_ = kNoActiveBubble;
|
|
|
| @@ -131,7 +149,7 @@ void ChromeSpeechRecognitionManagerDelegate::InfoBubbleButtonClicked(
|
| // the manager's public methods are reliable and will handle it properly.
|
| SpeechRecognitionManager::GetInstance()->AbortSession(session_id);
|
| } else if (button == SpeechRecognitionBubble::BUTTON_TRY_AGAIN) {
|
| - bubble_controller_->CloseBubble(session_id);
|
| + GetBubbleController()->CloseBubble(session_id);
|
| active_bubble_session_id_ = kNoActiveBubble;
|
| RestartLastSession();
|
| }
|
| @@ -142,7 +160,10 @@ void ChromeSpeechRecognitionManagerDelegate::InfoBubbleFocusChanged(
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| DCHECK_EQ(active_bubble_session_id_, session_id);
|
|
|
| - bubble_controller_->CloseBubble(session_id);
|
| + // Note, the session might have been destroyed, therefore avoid calls to the
|
| + // manager which imply its existance (e.g., GetSessionContext()).
|
| +
|
| + GetBubbleController()->CloseBubble(session_id);
|
| last_session_config_.reset();
|
| active_bubble_session_id_ = kNoActiveBubble;
|
|
|
| @@ -164,25 +185,36 @@ void ChromeSpeechRecognitionManagerDelegate::RestartLastSession() {
|
|
|
| void ChromeSpeechRecognitionManagerDelegate::OnRecognitionStart(
|
| int session_id) {
|
| - // Copy the configuration of the session (for the "try again" button).
|
| - last_session_config_.reset(new content::SpeechRecognitionSessionConfig(
|
| - SpeechRecognitionManager::GetInstance()->GetSessionConfig(session_id)));
|
| -
|
| - // Create and show the bubble.
|
| - DCHECK_EQ(active_bubble_session_id_, kNoActiveBubble);
|
| - active_bubble_session_id_ = session_id;
|
| const content::SpeechRecognitionSessionContext& context =
|
| SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
|
| - bubble_controller_->CreateBubble(session_id,
|
| - context.render_process_id,
|
| - context.render_view_id,
|
| - context.element_rect);
|
| - // TODO(primiano) Why not create directly the bubble in warmup mode?
|
| - bubble_controller_->SetBubbleWarmUpMode(session_id);
|
| +
|
| + if (RequiresBubble(session_id)) {
|
| + // Copy the configuration of the session (for the "try again" button).
|
| + last_session_config_.reset(new content::SpeechRecognitionSessionConfig(
|
| + 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);
|
| + }
|
| }
|
|
|
| void ChromeSpeechRecognitionManagerDelegate::OnAudioStart(int session_id) {
|
| - bubble_controller_->SetBubbleRecordingMode(session_id);
|
| + if (RequiresBubble(session_id)) {
|
| + GetBubbleController()->SetBubbleRecordingMode(session_id);
|
| + } else if (RequiresTrayIcon(session_id)) {
|
| + const content::SpeechRecognitionSessionContext& context =
|
| + SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
|
| + GetTrayIconController()->Show(context.context_name,
|
| + context.is_first_request_for_context);
|
| + }
|
| }
|
|
|
| void ChromeSpeechRecognitionManagerDelegate::OnEnvironmentEstimationComplete(
|
| @@ -198,16 +230,19 @@ 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 (active_bubble_session_id_ == session_id)
|
| - bubble_controller_->SetBubbleRecognizingMode(session_id);
|
| + if (RequiresBubble(session_id) && active_bubble_session_id_ == session_id) {
|
| + GetBubbleController()->SetBubbleRecognizingMode(session_id);
|
| + } else if (RequiresTrayIcon(session_id)) {
|
| + GetTrayIconController()->Hide();
|
| + }
|
| }
|
|
|
| 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 (active_bubble_session_id_ == session_id) {
|
| - bubble_controller_->CloseBubble(session_id);
|
| + if (RequiresBubble(session_id) && active_bubble_session_id_ == session_id) {
|
| + GetBubbleController()->CloseBubble(session_id);
|
| last_session_config_.reset();
|
| active_bubble_session_id_ = kNoActiveBubble;
|
| }
|
| @@ -218,6 +253,7 @@ void ChromeSpeechRecognitionManagerDelegate::OnRecognitionError(
|
| // An error can be dispatched when the bubble is not visible anymore.
|
| if (active_bubble_session_id_ != session_id)
|
| return;
|
| + DCHECK(RequiresBubble(session_id));
|
|
|
| int error_message_id = 0;
|
| switch (error.code) {
|
| @@ -250,17 +286,29 @@ void ChromeSpeechRecognitionManagerDelegate::OnRecognitionError(
|
| NOTREACHED() << "unknown error " << error.code;
|
| return;
|
| }
|
| - bubble_controller_->SetBubbleMessage(
|
| + GetBubbleController()->SetBubbleMessage(
|
| session_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)
|
| - bubble_controller_->SetBubbleInputVolume(session_id, volume, noise_volume);
|
| + if (active_bubble_session_id_ == session_id) {
|
| + DCHECK(RequiresBubble(session_id));
|
| + GetBubbleController()->SetBubbleInputVolume(session_id,
|
| + 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.
|
| }
|
|
|
| void ChromeSpeechRecognitionManagerDelegate::GetDiagnosticInformation(
|
| @@ -286,11 +334,20 @@ void ChromeSpeechRecognitionManagerDelegate::CheckRecognitionIsAllowed(
|
| int session_id,
|
| base::Callback<void(int session_id, bool is_allowed)> callback) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| - const content::SpeechRecognitionSessionContext& context =
|
| - SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
|
|
|
| + // We don't need any particular check for sessions not using a bubble. In such
|
| + // cases, we just notify it to the manager (calling-back synchronously, since
|
| + // we remain in the IO thread).
|
| + if (RequiresTrayIcon(session_id)) {
|
| + callback.Run(session_id, true /* is_allowed */);
|
| + return;
|
| + }
|
| +
|
| + // Sessions using bubbles, conversely, need a check on the renderer view type.
|
| // The check must be performed in the UI thread. We defer it posting to
|
| // CheckRenderViewType, which will issue the callback on our behalf.
|
| + const content::SpeechRecognitionSessionContext& context =
|
| + SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
|
| BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
| base::Bind(&CheckRenderViewType,
|
| session_id,
|
| @@ -330,4 +387,19 @@ void ChromeSpeechRecognitionManagerDelegate::CheckRenderViewType(
|
| base::Bind(callback, session_id, allowed));
|
| }
|
|
|
| +SpeechRecognitionBubbleController*
|
| +ChromeSpeechRecognitionManagerDelegate::GetBubbleController() {
|
| + if (!bubble_controller_.get())
|
| + bubble_controller_ = new SpeechRecognitionBubbleController(this);
|
| + return bubble_controller_.get();
|
| +}
|
| +
|
| +SpeechRecognitionTrayIconController*
|
| +ChromeSpeechRecognitionManagerDelegate::GetTrayIconController() {
|
| + if (!tray_icon_controller_.get())
|
| + tray_icon_controller_ = new SpeechRecognitionTrayIconController();
|
| + return tray_icon_controller_.get();
|
| +}
|
| +
|
| +
|
| } // namespace speech
|
|
|