Commit 9dc1c1a6 authored by satish@chromium.org's avatar satish@chromium.org

Cancel any pending speech recognitions when the dispatcher host terminates.

I have not added a new test for this because the existing test is flaky and
didn't seem right to add another flaky test like that. Instead I've added a TODO
to add a browser test for this case once the flaky test has been fixed.

BUG=none
TEST=manual

Review URL: http://codereview.chromium.org/6358007

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@71956 0039d316-1c4b-4281-b951-d872f2087c98
parent 2f7aa5e7
...@@ -42,14 +42,14 @@ class FakeSpeechInputManager : public SpeechInputManager { ...@@ -42,14 +42,14 @@ class FakeSpeechInputManager : public SpeechInputManager {
} }
// SpeechInputManager methods. // SpeechInputManager methods.
void StartRecognition(Delegate* delegate, virtual void StartRecognition(Delegate* delegate,
int caller_id, int caller_id,
int render_process_id, int render_process_id,
int render_view_id, int render_view_id,
const gfx::Rect& element_rect, const gfx::Rect& element_rect,
const std::string& language, const std::string& language,
const std::string& grammar, const std::string& grammar,
const std::string& origin_url) { const std::string& origin_url) {
VLOG(1) << "StartRecognition invoked."; VLOG(1) << "StartRecognition invoked.";
EXPECT_EQ(0, caller_id_); EXPECT_EQ(0, caller_id_);
EXPECT_EQ(NULL, delegate_); EXPECT_EQ(NULL, delegate_);
...@@ -60,17 +60,20 @@ class FakeSpeechInputManager : public SpeechInputManager { ...@@ -60,17 +60,20 @@ class FakeSpeechInputManager : public SpeechInputManager {
MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(this, MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(this,
&FakeSpeechInputManager::SetFakeRecognitionResult)); &FakeSpeechInputManager::SetFakeRecognitionResult));
} }
void CancelRecognition(int caller_id) { virtual void CancelRecognition(int caller_id) {
VLOG(1) << "CancelRecognition invoked."; VLOG(1) << "CancelRecognition invoked.";
EXPECT_EQ(caller_id_, caller_id); EXPECT_EQ(caller_id_, caller_id);
caller_id_ = 0; caller_id_ = 0;
delegate_ = NULL; delegate_ = NULL;
} }
void StopRecording(int caller_id) { virtual void StopRecording(int caller_id) {
VLOG(1) << "StopRecording invoked."; VLOG(1) << "StopRecording invoked.";
EXPECT_EQ(caller_id_, caller_id); EXPECT_EQ(caller_id_, caller_id);
// Nothing to do here since we aren't really recording. // Nothing to do here since we aren't really recording.
} }
virtual void CancelAllRequestsWithDelegate(Delegate* delegate) {
VLOG(1) << "CancelAllRequestsWithDelegate invoked.";
}
private: private:
void SetFakeRecognitionResult() { void SetFakeRecognitionResult() {
...@@ -167,6 +170,11 @@ SpeechInputManager* SpeechInputBrowserTest::speech_input_manager_ = NULL; ...@@ -167,6 +170,11 @@ SpeechInputManager* SpeechInputBrowserTest::speech_input_manager_ = NULL;
// check for sending many clicks in succession to the speech button and verify // check for sending many clicks in succession to the speech button and verify
// that it doesn't cause any crash but works as expected. This should act as the // that it doesn't cause any crash but works as expected. This should act as the
// test for http://crbug.com/59173 // test for http://crbug.com/59173
//
// TODO(satish): Similar to above, once this flakiness has been fixed add
// another test here to check that when speech recognition is in progress and
// a renderer crashes, we get a call to
// SpeechInputManager::CancelAllRequestsWithDelegate.
#if defined(OS_WIN) #if defined(OS_WIN)
#define MAYBE_TestBasicRecognition FLAKY_TestBasicRecognition #define MAYBE_TestBasicRecognition FLAKY_TestBasicRecognition
#else #else
......
...@@ -105,13 +105,21 @@ SpeechInputManager::AccessorMethod* ...@@ -105,13 +105,21 @@ SpeechInputManager::AccessorMethod*
SpeechInputDispatcherHost::manager_accessor_ = &SpeechInputManager::Get; SpeechInputDispatcherHost::manager_accessor_ = &SpeechInputManager::Get;
SpeechInputDispatcherHost::SpeechInputDispatcherHost(int render_process_id) SpeechInputDispatcherHost::SpeechInputDispatcherHost(int render_process_id)
: render_process_id_(render_process_id) { : render_process_id_(render_process_id),
may_have_pending_requests_(false) {
// This is initialized by Browser. Do not add any non-trivial // This is initialized by Browser. Do not add any non-trivial
// initialization here, instead do it lazily when required (e.g. see the // initialization here, instead do it lazily when required (e.g. see the
// method |manager()|) or add an Init() method. // method |manager()|) or add an Init() method.
} }
SpeechInputDispatcherHost::~SpeechInputDispatcherHost() { SpeechInputDispatcherHost::~SpeechInputDispatcherHost() {
// If the renderer crashed for some reason or if we didn't receive a proper
// Cancel/Stop call for an existing session, cancel such active sessions now.
// We first check if this dispatcher received any speech IPC requst so that
// we don't end up creating the speech input manager for web pages which don't
// use speech input.
if (may_have_pending_requests_)
manager()->CancelAllRequestsWithDelegate(this);
} }
SpeechInputManager* SpeechInputDispatcherHost::manager() { SpeechInputManager* SpeechInputDispatcherHost::manager() {
...@@ -131,6 +139,7 @@ bool SpeechInputDispatcherHost::OnMessageReceived( ...@@ -131,6 +139,7 @@ bool SpeechInputDispatcherHost::OnMessageReceived(
return true; return true;
} }
may_have_pending_requests_ = true;
IPC_BEGIN_MESSAGE_MAP_EX(SpeechInputDispatcherHost, message, IPC_BEGIN_MESSAGE_MAP_EX(SpeechInputDispatcherHost, message,
*message_was_ok) *message_was_ok)
IPC_MESSAGE_HANDLER(SpeechInputHostMsg_StartRecognition, IPC_MESSAGE_HANDLER(SpeechInputHostMsg_StartRecognition,
......
...@@ -51,6 +51,7 @@ class SpeechInputDispatcherHost : public BrowserMessageFilter, ...@@ -51,6 +51,7 @@ class SpeechInputDispatcherHost : public BrowserMessageFilter,
SpeechInputManager* manager(); SpeechInputManager* manager();
int render_process_id_; int render_process_id_;
bool may_have_pending_requests_; // Set if we received any speech IPC request
static SpeechInputManager::AccessorMethod* manager_accessor_; static SpeechInputManager::AccessorMethod* manager_accessor_;
......
...@@ -111,6 +111,8 @@ class SpeechInputManagerImpl : public SpeechInputManager, ...@@ -111,6 +111,8 @@ class SpeechInputManagerImpl : public SpeechInputManager,
const std::string& origin_url); const std::string& origin_url);
virtual void CancelRecognition(int caller_id); virtual void CancelRecognition(int caller_id);
virtual void StopRecording(int caller_id); virtual void StopRecording(int caller_id);
virtual void CancelAllRequestsWithDelegate(
SpeechInputManagerDelegate* delegate);
// SpeechRecognizer::Delegate methods. // SpeechRecognizer::Delegate methods.
virtual void SetRecognitionResult(int caller_id, virtual void SetRecognitionResult(int caller_id,
...@@ -265,6 +267,20 @@ void SpeechInputManagerImpl::CancelRecognition(int caller_id) { ...@@ -265,6 +267,20 @@ void SpeechInputManagerImpl::CancelRecognition(int caller_id) {
bubble_controller_->CloseBubble(caller_id); bubble_controller_->CloseBubble(caller_id);
} }
void SpeechInputManagerImpl::CancelAllRequestsWithDelegate(
SpeechInputManagerDelegate* delegate) {
SpeechRecognizerMap::iterator it = requests_.begin();
while (it != requests_.end()) {
if (it->second.delegate == delegate) {
CancelRecognition(it->first);
// This map will have very few elements so it is simpler to restart.
it = requests_.begin();
} else {
++it;
}
}
}
void SpeechInputManagerImpl::StopRecording(int caller_id) { void SpeechInputManagerImpl::StopRecording(int caller_id) {
DCHECK(HasPendingRequest(caller_id)); DCHECK(HasPendingRequest(caller_id));
requests_[caller_id].recognizer->StopRecording(); requests_[caller_id].recognizer->StopRecording();
......
...@@ -63,6 +63,8 @@ class SpeechInputManager { ...@@ -63,6 +63,8 @@ class SpeechInputManager {
const std::string& origin_url) = 0; const std::string& origin_url) = 0;
virtual void CancelRecognition(int caller_id) = 0; virtual void CancelRecognition(int caller_id) = 0;
virtual void StopRecording(int caller_id) = 0; virtual void StopRecording(int caller_id) = 0;
virtual void CancelAllRequestsWithDelegate(Delegate* delegate) = 0;
}; };
// This typedef is to workaround the issue with certain versions of // This typedef is to workaround the issue with certain versions of
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment