diff options
author | primiano@chromium.org <primiano@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-02 19:22:28 +0000 |
---|---|---|
committer | primiano@chromium.org <primiano@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-02 19:22:28 +0000 |
commit | 6df4ab90fa691851662bd8fd80b167cda56972fc (patch) | |
tree | b5c01f23d1fe7792f4911791e50a00679666f12a /content/browser/speech/speech_recognition_manager_impl.cc | |
parent | 10c76b375f6b01648430a32284f1a9e98bb6329c (diff) | |
download | chromium_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.cc | 17 |
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) { } |