diff options
author | satish@chromium.org <satish@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-17 11:40:22 +0000 |
---|---|---|
committer | satish@chromium.org <satish@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-17 11:40:22 +0000 |
commit | c61a6b6d9e4315174806366425fece0da631cc7c (patch) | |
tree | 49520f1da513debb0b3264e9317e92ecd89b77f6 /chrome/browser/speech | |
parent | 04d75b6f37e104c672db22cbbba84fa3b21a510d (diff) | |
download | chromium_src-c61a6b6d9e4315174806366425fece0da631cc7c.zip chromium_src-c61a6b6d9e4315174806366425fece0da631cc7c.tar.gz chromium_src-c61a6b6d9e4315174806366425fece0da631cc7c.tar.bz2 |
Support for multiple speech enabled elements in same page.
This is the chromium side of https://bugs.webkit.org/show_bug.cgi?id=43922.
For all speech input requests WebKit now sends a 'requestId' which identifies the input element within the page. This requestId is returned back to WebKit in all the speech input callbacks/events. Within chromium, the pair (render view id, request id) uniquely identifies a caller and we introduce the SpeechInputCallerId to hold this data. All code which was previously using render view id now uses this caller id.
Once this is working fully on both ends I'll add relevant browser tests.
BUG=none
TEST=manually
Review URL: http://codereview.chromium.org/3130018
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@56333 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/speech')
-rw-r--r-- | chrome/browser/speech/speech_input_browsertest.cc | 32 | ||||
-rw-r--r-- | chrome/browser/speech/speech_input_dispatcher_host.cc | 47 | ||||
-rw-r--r-- | chrome/browser/speech/speech_input_dispatcher_host.h | 15 | ||||
-rw-r--r-- | chrome/browser/speech/speech_input_manager.cc | 87 | ||||
-rw-r--r-- | chrome/browser/speech/speech_input_manager.h | 14 | ||||
-rw-r--r-- | chrome/browser/speech/speech_recognizer.cc | 17 | ||||
-rw-r--r-- | chrome/browser/speech/speech_recognizer.h | 18 | ||||
-rw-r--r-- | chrome/browser/speech/speech_recognizer_unittest.cc | 10 |
8 files changed, 139 insertions, 101 deletions
diff --git a/chrome/browser/speech/speech_input_browsertest.cc b/chrome/browser/speech/speech_input_browsertest.cc index 942118f..f43167b 100644 --- a/chrome/browser/speech/speech_input_browsertest.cc +++ b/chrome/browser/speech/speech_input_browsertest.cc @@ -30,39 +30,41 @@ const char* kTestResult = "Pictures of the moon"; class FakeSpeechInputManager : public SpeechInputManager { public: explicit FakeSpeechInputManager(Delegate* delegate) - : render_view_id_(0), + : caller_id_(0, 0), delegate_(delegate) { } // SpeechInputManager methods. - void StartRecognition(int render_view_id) { - EXPECT_EQ(0, render_view_id_); - render_view_id_ = render_view_id; + void StartRecognition(const SpeechInputCallerId& caller_id) { + EXPECT_EQ(0, caller_id_.first); + caller_id_ = caller_id; // Give the fake result in a short while. MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(this, &FakeSpeechInputManager::SetFakeRecognitionResult)); } - void CancelRecognition(int render_view_id) { - EXPECT_EQ(render_view_id_, render_view_id); - render_view_id_ = 0; + void CancelRecognition(const SpeechInputCallerId& caller_id) { + EXPECT_EQ(caller_id_.first, caller_id.first); + EXPECT_EQ(caller_id_.second, caller_id.second); + caller_id_ = SpeechInputCallerId(0, 0); } - void StopRecording(int render_view_id) { - EXPECT_EQ(render_view_id_, render_view_id); + void StopRecording(const SpeechInputCallerId& caller_id) { + EXPECT_EQ(caller_id_.first, caller_id.first); + EXPECT_EQ(caller_id_.second, caller_id.second); // Nothing to do here since we aren't really recording. } private: void SetFakeRecognitionResult() { - if (render_view_id_) { // Do a check in case we were cancelled.. - delegate_->DidCompleteRecording(render_view_id_); - delegate_->SetRecognitionResult(render_view_id_, + if (caller_id_.first) { // Do a check in case we were cancelled.. + delegate_->DidCompleteRecording(caller_id_); + delegate_->SetRecognitionResult(caller_id_, ASCIIToUTF16(kTestResult)); - delegate_->DidCompleteRecognition(render_view_id_); - render_view_id_ = 0; + delegate_->DidCompleteRecognition(caller_id_); + caller_id_ = SpeechInputCallerId(0, 0); } } - int render_view_id_; + SpeechInputCallerId caller_id_; Delegate* delegate_; }; diff --git a/chrome/browser/speech/speech_input_dispatcher_host.cc b/chrome/browser/speech/speech_input_dispatcher_host.cc index 8346cbe..84049aa 100644 --- a/chrome/browser/speech/speech_input_dispatcher_host.cc +++ b/chrome/browser/speech/speech_input_dispatcher_host.cc @@ -50,22 +50,25 @@ bool SpeechInputDispatcherHost::OnMessageReceived( return handled; } -void SpeechInputDispatcherHost::OnStartRecognition(int render_view_id) { +void SpeechInputDispatcherHost::OnStartRecognition(int render_view_id, + int request_id) { LOG(INFO) << "SpeechInputDispatcherHost: start recognition" << render_view_id; - manager()->StartRecognition(render_view_id); + manager()->StartRecognition(SpeechInputCallerId(render_view_id, request_id)); } -void SpeechInputDispatcherHost::OnCancelRecognition(int render_view_id) { +void SpeechInputDispatcherHost::OnCancelRecognition(int render_view_id, + int request_id) { LOG(INFO) << "SpeechInputDispatcherHost: cancel recognition" << render_view_id; - manager()->CancelRecognition(render_view_id); + manager()->CancelRecognition(SpeechInputCallerId(render_view_id, request_id)); } -void SpeechInputDispatcherHost::OnStopRecording(int render_view_id) { +void SpeechInputDispatcherHost::OnStopRecording(int render_view_id, + int request_id) { LOG(INFO) << "SpeechInputDispatcherHost: stop recording" << render_view_id; - manager()->StopRecording(render_view_id); + manager()->StopRecording(SpeechInputCallerId(render_view_id, request_id)); } void SpeechInputDispatcherHost::SendMessageToRenderView(IPC::Message* message, @@ -76,26 +79,38 @@ void SpeechInputDispatcherHost::SendMessageToRenderView(IPC::Message* message, } -void SpeechInputDispatcherHost::SetRecognitionResult(int render_view_id, - const string16& result) { +void SpeechInputDispatcherHost::SetRecognitionResult( + const SpeechInputCallerId& caller_id, const string16& result) { DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); + int caller_render_view_id = caller_id.first; + int caller_request_id = caller_id.second; SendMessageToRenderView( - new ViewMsg_SpeechInput_SetRecognitionResult(render_view_id, result), - render_view_id); + new ViewMsg_SpeechInput_SetRecognitionResult(caller_render_view_id, + caller_request_id, + result), + caller_render_view_id); } -void SpeechInputDispatcherHost::DidCompleteRecording(int render_view_id) { +void SpeechInputDispatcherHost::DidCompleteRecording( + const SpeechInputCallerId& caller_id) { DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); + int caller_render_view_id = caller_id.first; + int caller_request_id = caller_id.second; SendMessageToRenderView( - new ViewMsg_SpeechInput_RecordingComplete(render_view_id), - render_view_id); + new ViewMsg_SpeechInput_RecordingComplete(caller_render_view_id, + caller_request_id), + caller_render_view_id); } -void SpeechInputDispatcherHost::DidCompleteRecognition(int render_view_id) { +void SpeechInputDispatcherHost::DidCompleteRecognition( + const SpeechInputCallerId& caller_id) { DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); + int caller_render_view_id = caller_id.first; + int caller_request_id = caller_id.second; SendMessageToRenderView( - new ViewMsg_SpeechInput_RecognitionComplete(render_view_id), - render_view_id); + new ViewMsg_SpeechInput_RecognitionComplete(caller_render_view_id, + caller_request_id), + caller_render_view_id); } } // namespace speech_input diff --git a/chrome/browser/speech/speech_input_dispatcher_host.h b/chrome/browser/speech/speech_input_dispatcher_host.h index 9f2e882..c84ef5f 100644 --- a/chrome/browser/speech/speech_input_dispatcher_host.h +++ b/chrome/browser/speech/speech_input_dispatcher_host.h @@ -8,8 +8,8 @@ #include "base/basictypes.h" #include "base/ref_counted.h" #include "base/scoped_ptr.h" +#include "chrome/browser/speech/speech_input_manager.h" #include "ipc/ipc_message.h" -#include "speech_input_manager.h" namespace speech_input { @@ -23,9 +23,10 @@ class SpeechInputDispatcherHost explicit SpeechInputDispatcherHost(int resource_message_filter_process_id); // SpeechInputManager::Delegate methods. - void SetRecognitionResult(int render_view_id, const string16& result); - void DidCompleteRecording(int render_view_id); - void DidCompleteRecognition(int render_view_id); + void SetRecognitionResult(const SpeechInputCallerId& caller_id, + const string16& result); + void DidCompleteRecording(const SpeechInputCallerId& caller_id); + void DidCompleteRecognition(const SpeechInputCallerId& caller_id); // Called to possibly handle the incoming IPC message. Returns true if // handled. @@ -41,9 +42,9 @@ class SpeechInputDispatcherHost virtual ~SpeechInputDispatcherHost(); void SendMessageToRenderView(IPC::Message* message, int render_view_id); - void OnStartRecognition(int render_view_id); - void OnCancelRecognition(int render_view_id); - void OnStopRecording(int render_view_id); + void OnStartRecognition(int render_view_id, int request_id); + void OnCancelRecognition(int render_view_id, int request_id); + void OnStopRecording(int render_view_id, int request_id); // Returns the speech input manager to forward events to, creating one if // needed. diff --git a/chrome/browser/speech/speech_input_manager.cc b/chrome/browser/speech/speech_input_manager.cc index ae7c845..dd2bb60 100644 --- a/chrome/browser/speech/speech_input_manager.cc +++ b/chrome/browser/speech/speech_input_manager.cc @@ -5,7 +5,6 @@ #include "chrome/browser/speech/speech_input_manager.h" #include "base/ref_counted.h" -#include "chrome/browser/speech/speech_recognizer.h" #include <map> namespace speech_input { @@ -17,21 +16,22 @@ public: virtual ~SpeechInputManagerImpl(); // SpeechInputManager methods. - void StartRecognition(int render_view_id); - void CancelRecognition(int render_view_id); - void StopRecording(int render_view_id); + void StartRecognition(const SpeechInputCallerId& caller_id); + void CancelRecognition(const SpeechInputCallerId& caller_id); + void StopRecording(const SpeechInputCallerId& caller_id); // SpeechRecognizer::Delegate methods. - void SetRecognitionResult(int render_view_id, bool error, + void SetRecognitionResult(const SpeechInputCallerId& caller_id, bool error, const string16& value); - void DidCompleteRecording(int render_view_id); - void DidCompleteRecognition(int render_view_id); + void DidCompleteRecording(const SpeechInputCallerId& caller_id); + void DidCompleteRecognition(const SpeechInputCallerId& caller_id); private: SpeechInputManagerDelegate* delegate_; - typedef std::map<int, scoped_refptr<SpeechRecognizer> > SpeechRecognizerMap; + typedef std::map<SpeechInputCallerId, + scoped_refptr<SpeechRecognizer> > SpeechRecognizerMap; SpeechRecognizerMap recognizers_; - int recording_render_view_id_; + SpeechInputCallerId recording_caller_id_; }; SpeechInputManager* SpeechInputManager::Create( @@ -42,58 +42,67 @@ SpeechInputManager* SpeechInputManager::Create( SpeechInputManagerImpl::SpeechInputManagerImpl( SpeechInputManagerDelegate* delegate) : delegate_(delegate), - recording_render_view_id_(0) { + recording_caller_id_(0, 0) { } SpeechInputManagerImpl::~SpeechInputManagerImpl() { while (recognizers_.begin() != recognizers_.end()) - recognizers_.begin()->second->CancelRecognition(); + CancelRecognition(recognizers_.begin()->first); } -void SpeechInputManagerImpl::StartRecognition(int render_view_id) { +void SpeechInputManagerImpl::StartRecognition( + const SpeechInputCallerId& caller_id) { // Make sure we are not already doing recognition for this render view. - DCHECK(recognizers_.find(render_view_id) == recognizers_.end()); - if (recognizers_.find(render_view_id) != recognizers_.end()) + DCHECK(recognizers_.find(caller_id) == recognizers_.end()); + if (recognizers_.find(caller_id) != recognizers_.end()) return; - // If we are currently recording audio for another caller, abort that now. - if (recording_render_view_id_) - CancelRecognition(recording_render_view_id_); + // If we are currently recording audio for another caller, abort that cleanly. + if (recording_caller_id_.first != 0) { + SpeechInputCallerId active_caller = recording_caller_id_; + CancelRecognition(active_caller); + DidCompleteRecording(active_caller); + DidCompleteRecognition(active_caller); + } - recording_render_view_id_ = render_view_id; - recognizers_[render_view_id] = new SpeechRecognizer(this, render_view_id); - recognizers_[render_view_id]->StartRecording(); + recording_caller_id_ = caller_id; + recognizers_[caller_id] = new SpeechRecognizer(this, caller_id); + recognizers_[caller_id]->StartRecording(); } -void SpeechInputManagerImpl::CancelRecognition(int render_view_id) { - DCHECK(recognizers_.find(render_view_id) != recognizers_.end()); - if (recognizers_.find(render_view_id) != recognizers_.end()) { - recognizers_[render_view_id]->CancelRecognition(); +void SpeechInputManagerImpl::CancelRecognition( + const SpeechInputCallerId& caller_id) { + DCHECK(recognizers_.find(caller_id) != recognizers_.end()); + if (recognizers_.find(caller_id) != recognizers_.end()) { + recognizers_[caller_id]->CancelRecognition(); + recognizers_.erase(caller_id); } } -void SpeechInputManagerImpl::StopRecording(int render_view_id) { - DCHECK(recognizers_.find(render_view_id) != recognizers_.end()); - if (recognizers_.find(render_view_id) != recognizers_.end()) { - recognizers_[render_view_id]->StopRecording(); +void SpeechInputManagerImpl::StopRecording( + const SpeechInputCallerId& caller_id) { + DCHECK(recognizers_.find(caller_id) != recognizers_.end()); + if (recognizers_.find(caller_id) != recognizers_.end()) { + recognizers_[caller_id]->StopRecording(); } } -void SpeechInputManagerImpl::SetRecognitionResult(int render_view_id, - bool error, - const string16& value) { - delegate_->SetRecognitionResult(render_view_id, (error ? string16() : value)); +void SpeechInputManagerImpl::SetRecognitionResult( + const SpeechInputCallerId& caller_id, bool error, const string16& value) { + delegate_->SetRecognitionResult(caller_id, (error ? string16() : value)); } -void SpeechInputManagerImpl::DidCompleteRecording(int render_view_id) { - DCHECK(recording_render_view_id_ == render_view_id); - recording_render_view_id_ = 0; - delegate_->DidCompleteRecording(render_view_id); +void SpeechInputManagerImpl::DidCompleteRecording( + const SpeechInputCallerId& caller_id) { + DCHECK(recording_caller_id_ == caller_id); + recording_caller_id_.first = 0; + delegate_->DidCompleteRecording(caller_id); } -void SpeechInputManagerImpl::DidCompleteRecognition(int render_view_id) { - recognizers_.erase(render_view_id); - delegate_->DidCompleteRecognition(render_view_id); +void SpeechInputManagerImpl::DidCompleteRecognition( + const SpeechInputCallerId& caller_id) { + recognizers_.erase(caller_id); + delegate_->DidCompleteRecognition(caller_id); } } // namespace speech_input diff --git a/chrome/browser/speech/speech_input_manager.h b/chrome/browser/speech/speech_input_manager.h index cac3294..5c5dc8b 100644 --- a/chrome/browser/speech/speech_input_manager.h +++ b/chrome/browser/speech/speech_input_manager.h @@ -7,6 +7,7 @@ #include "base/basictypes.h" #include "base/ref_counted.h" +#include "chrome/browser/speech/speech_recognizer.h" #include "ipc/ipc_message.h" namespace speech_input { @@ -20,10 +21,11 @@ class SpeechInputManager { // Implemented by the dispatcher host to relay events to the render views. class Delegate { public: - virtual void SetRecognitionResult(int render_view_id, + virtual void SetRecognitionResult(const SpeechInputCallerId& caller_id, const string16& value) = 0; - virtual void DidCompleteRecording(int render_view_id) = 0; - virtual void DidCompleteRecognition(int render_view_id) = 0; + virtual void DidCompleteRecording(const SpeechInputCallerId& caller_id) = 0; + virtual void DidCompleteRecognition( + const SpeechInputCallerId& caller_id) = 0; }; // Factory method to create new instances. @@ -34,9 +36,9 @@ class SpeechInputManager { virtual ~SpeechInputManager() {} // Handlers for requests from render views. - virtual void StartRecognition(int render_view_id) = 0; - virtual void CancelRecognition(int render_view_id) = 0; - virtual void StopRecording(int render_view_id) = 0; + virtual void StartRecognition(const SpeechInputCallerId& caller_id) = 0; + virtual void CancelRecognition(const SpeechInputCallerId& caller_id) = 0; + virtual void StopRecording(const SpeechInputCallerId& caller_id) = 0; }; // This typedef is to workaround the issue with certain versions of diff --git a/chrome/browser/speech/speech_recognizer.cc b/chrome/browser/speech/speech_recognizer.cc index 0f8b116..02c67a3 100644 --- a/chrome/browser/speech/speech_recognizer.cc +++ b/chrome/browser/speech/speech_recognizer.cc @@ -24,9 +24,10 @@ const int kNumBitsPerAudioSample = 16; namespace speech_input { -SpeechRecognizer::SpeechRecognizer(Delegate* delegate, int render_view_id) +SpeechRecognizer::SpeechRecognizer(Delegate* delegate, + const SpeechInputCallerId& caller_id) : delegate_(delegate), - render_view_id_(render_view_id) { + caller_id_(caller_id) { } SpeechRecognizer::~SpeechRecognizer() { @@ -80,13 +81,13 @@ void SpeechRecognizer::StopRecording() { LOG(INFO) << "SpeechRecognizer stopping record."; audio_controller_->Close(); audio_controller_ = NULL; // Releases the ref ptr. - delegate_->DidCompleteRecording(render_view_id_); + delegate_->DidCompleteRecording(caller_id_); // If we haven't got any audio yet end the recognition sequence here. if (audio_buffers_.empty()) { // Guard against the delegate freeing us until we finish our job. scoped_refptr<SpeechRecognizer> me(this); - delegate_->DidCompleteRecognition(render_view_id_); + delegate_->DidCompleteRecognition(caller_id_); return; } @@ -139,8 +140,8 @@ void SpeechRecognizer::HandleOnError(int error_code) { return; CancelRecognition(); - delegate_->DidCompleteRecording(render_view_id_); - delegate_->DidCompleteRecognition(render_view_id_); + delegate_->DidCompleteRecording(caller_id_); + delegate_->DidCompleteRecognition(caller_id_); } void SpeechRecognizer::OnData(AudioInputController* controller, @@ -170,11 +171,11 @@ void SpeechRecognizer::HandleOnData(string* data) { } void SpeechRecognizer::SetRecognitionResult(bool error, const string16& value) { - delegate_->SetRecognitionResult(render_view_id_, error, value); + delegate_->SetRecognitionResult(caller_id_, error, value); // Guard against the delegate freeing us until we finish our job. scoped_refptr<SpeechRecognizer> me(this); - delegate_->DidCompleteRecognition(render_view_id_); + delegate_->DidCompleteRecognition(caller_id_); } } // namespace speech_input diff --git a/chrome/browser/speech/speech_recognizer.h b/chrome/browser/speech/speech_recognizer.h index fd8c7c4..2a13c60 100644 --- a/chrome/browser/speech/speech_recognizer.h +++ b/chrome/browser/speech/speech_recognizer.h @@ -11,9 +11,15 @@ #include "chrome/browser/speech/speech_recognition_request.h" #include <list> #include <string> +#include <utility> namespace speech_input { +// Holds the details of a particular webkit element making a speech request. +// SpeechInputCallerId::first holds the ID of the render view and +// SpeechInputCallerId::second holds the request ID given by the element. +typedef std::pair<int, int> SpeechInputCallerId; + // Records audio, sends recorded audio to server and translates server response // to recognition result. class SpeechRecognizer @@ -24,24 +30,26 @@ class SpeechRecognizer // Implemented by the caller to receive recognition events. class Delegate { public: - virtual void SetRecognitionResult(int render_view_id, bool error, + virtual void SetRecognitionResult(const SpeechInputCallerId& caller_id, + bool error, const string16& value) = 0; // Invoked when audio recording stops, either due to the end pointer // detecting silence in user input or if |StopRecording| was called. The // delegate has to wait until |DidCompleteRecognition| is invoked before // destroying the |SpeechRecognizer| object. - virtual void DidCompleteRecording(int render_view_id) = 0; + virtual void DidCompleteRecording(const SpeechInputCallerId& caller_id) = 0; // This is guaranteed to be the last method invoked in the recognition // sequence and the |SpeechRecognizer| object can be freed up if necessary. - virtual void DidCompleteRecognition(int render_view_id) = 0; + virtual void DidCompleteRecognition( + const SpeechInputCallerId& caller_id) = 0; protected: virtual ~Delegate() {} }; - SpeechRecognizer(Delegate* delegate, int render_view_id); + SpeechRecognizer(Delegate* delegate, const SpeechInputCallerId& caller_id); ~SpeechRecognizer(); // Starts audio recording and does recognition after recording ends. The same @@ -76,7 +84,7 @@ class SpeechRecognizer void HandleOnData(std::string* data); Delegate* delegate_; - int render_view_id_; + SpeechInputCallerId caller_id_; // Buffer holding the recorded audio. Owns the strings inside the list. typedef std::list<std::string*> AudioBufferQueue; diff --git a/chrome/browser/speech/speech_recognizer_unittest.cc b/chrome/browser/speech/speech_recognizer_unittest.cc index 1068364..5d2c845 100644 --- a/chrome/browser/speech/speech_recognizer_unittest.cc +++ b/chrome/browser/speech/speech_recognizer_unittest.cc @@ -21,7 +21,7 @@ class SpeechRecognizerTest : public SpeechRecognizerDelegate, SpeechRecognizerTest() : io_thread_(ChromeThread::IO, &message_loop_), ALLOW_THIS_IN_INITIALIZER_LIST( - recognizer_(new SpeechRecognizer(this, 1))) { + recognizer_(new SpeechRecognizer(this, SpeechInputCallerId(1,1)))) { } void StartTest() { @@ -29,16 +29,16 @@ class SpeechRecognizerTest : public SpeechRecognizerDelegate, } // SpeechRecognizer::Delegate methods. - virtual void SetRecognitionResult(int render_view_id, bool error, - const string16& result) { + virtual void SetRecognitionResult(const SpeechInputCallerId& caller_id, + bool error, const string16& result) { result_received_ = true; } - virtual void DidCompleteRecording(int render_view_id) { + virtual void DidCompleteRecording(const SpeechInputCallerId& caller_id) { recording_complete_ = true; } - virtual void DidCompleteRecognition(int render_view_id) { + virtual void DidCompleteRecognition(const SpeechInputCallerId& caller_id) { recognition_complete_ = true; } |