summaryrefslogtreecommitdiffstats
path: root/content/browser/speech/speech_recognition_manager_impl.cc
diff options
context:
space:
mode:
authorprimiano@chromium.org <primiano@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-02 19:22:28 +0000
committerprimiano@chromium.org <primiano@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-02 19:22:28 +0000
commit6df4ab90fa691851662bd8fd80b167cda56972fc (patch)
treeb5c01f23d1fe7792f4911791e50a00679666f12a /content/browser/speech/speech_recognition_manager_impl.cc
parent10c76b375f6b01648430a32284f1a9e98bb6329c (diff)
downloadchromium_src-6df4ab90fa691851662bd8fd80b167cda56972fc.zip
chromium_src-6df4ab90fa691851662bd8fd80b167cda56972fc.tar.gz
chromium_src-6df4ab90fa691851662bd8fd80b167cda56972fc.tar.bz2
Web Speech API: Fix a race condition causing renderer crash.
The introduction of the MediaRequestPermission (i.e. infobar) has opened a race window which causes a recognition session to be aborted twice, causing a consequent crash on the renderer. The race window is the following: 1) Session 1 is started (SpeechRecognitionManagerImpl::StartSession) 2) Security checks for session 1 are started asynchronously (delegate_->CheckRecognitionIsAllowed). 3) Session 2 is started. This causes an immediate abort of session 1. 4) The oustanding security check for session 1 completes and returns a nack. The nack causes an abort of session 1 (in RecognitionAllowedCallback). However, session 1 was already aborted in 3). 5) The double abort is not tolerated by the renderer, which crashes. This CL closes the race window with a not-so-elegant fix. A refactoring of the speech_recognition_manager_impl.cc is STRONGLY adviced (Hint: use and extend the already existing FSM to keep track of the asynchronous completion of security checks. Don't introduce extra state with extra variables). BUG=296690,116954 Review URL: https://codereview.chromium.org/25550003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@226523 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser/speech/speech_recognition_manager_impl.cc')
-rw-r--r--content/browser/speech/speech_recognition_manager_impl.cc17
1 files changed, 14 insertions, 3 deletions
diff --git a/content/browser/speech/speech_recognition_manager_impl.cc b/content/browser/speech/speech_recognition_manager_impl.cc
index 51cf027..bdc9d1c 100644
--- a/content/browser/speech/speech_recognition_manager_impl.cc
+++ b/content/browser/speech/speech_recognition_manager_impl.cc
@@ -184,10 +184,15 @@ void SpeechRecognitionManagerImpl::RecognitionAllowedCallback(int session_id,
if (!SessionExists(session_id))
return;
+ SessionsTable::iterator iter = sessions_.find(session_id);
+ DCHECK(iter != sessions_.end());
+ Session* session = iter->second;
+
+ if (session->abort_requested)
+ return;
+
if (ask_user) {
- SessionsTable::iterator iter = sessions_.find(session_id);
- DCHECK(iter != sessions_.end());
- SpeechRecognitionSessionContext& context = iter->second->context;
+ SpeechRecognitionSessionContext& context = session->context;
context.label = media_stream_manager_->MakeMediaAccessRequest(
context.render_process_id,
context.render_view_id,
@@ -253,6 +258,11 @@ void SpeechRecognitionManagerImpl::AbortSession(int session_id) {
SessionsTable::iterator iter = sessions_.find(session_id);
iter->second->ui.reset();
+ if (iter->second->abort_requested)
+ return;
+
+ iter->second->abort_requested = true;
+
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&SpeechRecognitionManagerImpl::DispatchEvent,
@@ -676,6 +686,7 @@ void SpeechRecognitionManagerImpl::ShowAudioInputSettings() {
SpeechRecognitionManagerImpl::Session::Session()
: id(kSessionIDInvalid),
+ abort_requested(false),
listener_is_active(true) {
}