diff options
-rw-r--r-- | content/browser/speech/speech_input_manager.cc | 96 | ||||
-rw-r--r-- | content/browser/speech/speech_input_manager.h | 5 |
2 files changed, 92 insertions, 9 deletions
diff --git a/content/browser/speech/speech_input_manager.cc b/content/browser/speech/speech_input_manager.cc index b597c22..b102b1d 100644 --- a/content/browser/speech/speech_input_manager.cc +++ b/content/browser/speech/speech_input_manager.cc @@ -5,14 +5,52 @@ #include "content/browser/speech/speech_input_manager.h" #include "base/bind.h" +#include "content/browser/renderer_host/render_view_host.h" +#include "content/browser/renderer_host/render_view_host_delegate.h" #include "content/browser/speech/speech_input_preferences.h" #include "content/public/browser/browser_thread.h" +#include "content/public/common/view_types.h" #include "media/audio/audio_manager.h" using content::BrowserThread; namespace speech_input { +struct SpeechInputManager::SpeechInputParams { + SpeechInputParams(Delegate* delegate, + int caller_id, + int render_process_id, + int render_view_id, + const gfx::Rect& element_rect, + const std::string& language, + const std::string& grammar, + const std::string& origin_url, + net::URLRequestContextGetter* context_getter, + SpeechInputPreferences* speech_input_prefs) + : delegate(delegate), + caller_id(caller_id), + render_process_id(render_process_id), + render_view_id(render_view_id), + element_rect(element_rect), + language(language), + grammar(grammar), + origin_url(origin_url), + context_getter(context_getter), + speech_input_prefs(speech_input_prefs) { + } + + Delegate* delegate; + int caller_id; + int render_process_id; + int render_view_id; + gfx::Rect element_rect; + std::string language; + std::string grammar; + std::string origin_url; + net::URLRequestContextGetter* context_getter; + SpeechInputPreferences* speech_input_prefs; +}; + SpeechInputManager::SpeechInputManager() : can_report_metrics_(false), recording_caller_id_(0) { @@ -58,21 +96,58 @@ void SpeechInputManager::StartRecognition( const std::string& origin_url, net::URLRequestContextGetter* context_getter, SpeechInputPreferences* speech_input_prefs) { - DCHECK(!HasPendingRequest(caller_id)); + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&SpeechInputManager::CheckRenderViewTypeAndStartRecognition, + base::Unretained(this), SpeechInputParams(delegate, caller_id, + render_process_id, render_view_id, element_rect, language, grammar, + origin_url, context_getter, speech_input_prefs))); +} + +void SpeechInputManager::CheckRenderViewTypeAndStartRecognition( + const SpeechInputParams& params) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + RenderViewHost* render_view_host = RenderViewHost::FromID( + params.render_process_id, params.render_view_id); + if (!render_view_host || !render_view_host->delegate()) + return; + + // For host delegates other than TabContents we can't reliably show a popup, + // including the speech input bubble. In these cases for privacy reasons we + // don't want to start recording if the user can't be properly notified. + // An example of this is trying to show the speech input bubble within an + // extension popup: http://crbug.com/92083. In these situations the speech + // input extension API should be used instead. + if (render_view_host->delegate()->GetRenderViewType() == + content::VIEW_TYPE_TAB_CONTENTS) { + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&SpeechInputManager::ProceedStartingRecognition, + base::Unretained(this), params)); + } +} + +void SpeechInputManager::ProceedStartingRecognition( + const SpeechInputParams& params) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK(!HasPendingRequest(params.caller_id)); ShowRecognitionRequested( - caller_id, render_process_id, render_view_id, element_rect); + params.caller_id, params.render_process_id, params.render_view_id, + params.element_rect); GetRequestInfo(&can_report_metrics_, &request_info_); - SpeechInputRequest* request = &requests_[caller_id]; - request->delegate = delegate; + SpeechInputRequest* request = &requests_[params.caller_id]; + request->delegate = params.delegate; request->recognizer = new SpeechRecognizer( - this, caller_id, language, grammar, context_getter, - speech_input_prefs->filter_profanities(), - request_info_, can_report_metrics_ ? origin_url : ""); + this, params.caller_id, params.language, params.grammar, + params.context_getter, params.speech_input_prefs->filter_profanities(), + request_info_, can_report_metrics_ ? params.origin_url : ""); request->is_active = false; - StartRecognitionForRequest(caller_id); + StartRecognitionForRequest(params.caller_id); } void SpeechInputManager::StartRecognitionForRequest(int caller_id) { @@ -119,7 +194,10 @@ void SpeechInputManager::CancelAllRequestsWithDelegate( } void SpeechInputManager::StopRecording(int caller_id) { - DCHECK(HasPendingRequest(caller_id)); + // No pending requests on extension popups. + if (!HasPendingRequest(caller_id)) + return; + requests_[caller_id].recognizer->StopRecording(); } diff --git a/content/browser/speech/speech_input_manager.h b/content/browser/speech/speech_input_manager.h index a342dc3..3c37aff 100644 --- a/content/browser/speech/speech_input_manager.h +++ b/content/browser/speech/speech_input_manager.h @@ -147,8 +147,13 @@ class CONTENT_EXPORT SpeechInputManager : public SpeechRecognizerDelegate { bool is_active; // Set to true when recording or recognition is going on. }; + struct SpeechInputParams; + Delegate* GetDelegate(int caller_id) const; + void CheckRenderViewTypeAndStartRecognition(const SpeechInputParams& params); + void ProceedStartingRecognition(const SpeechInputParams& params); + typedef std::map<int, SpeechInputRequest> SpeechRecognizerMap; SpeechRecognizerMap requests_; std::string request_info_; |