| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/speech/speech_input_dispatcher_host.h" | 5 #include "content/browser/speech/speech_recognition_dispatcher_host.h" |
| 6 | 6 |
| 7 #include "base/lazy_instance.h" | 7 #include "base/lazy_instance.h" |
| 8 #include "content/browser/speech/speech_input_manager_impl.h" | 8 #include "content/browser/speech/speech_recognition_manager_impl.h" |
| 9 #include "content/browser/speech/speech_recognizer_impl.h" | 9 #include "content/browser/speech/speech_recognizer_impl.h" |
| 10 #include "content/common/speech_input_messages.h" | 10 #include "content/common/speech_recognition_messages.h" |
| 11 #include "content/public/browser/speech_input_preferences.h" | 11 #include "content/public/browser/speech_recognition_preferences.h" |
| 12 | 12 |
| 13 using content::BrowserThread; | 13 using content::BrowserThread; |
| 14 | 14 |
| 15 namespace speech_input { | 15 namespace speech { |
| 16 | 16 |
| 17 //----------------------------- SpeechInputCallers ----------------------------- | 17 //----------------------------- Callers ----------------------------- |
| 18 | 18 |
| 19 // A singleton class to map the tuple | 19 // A singleton class to map the tuple |
| 20 // (render-process-id, render-view-id, requestid) to a single ID which is passed | 20 // (render-process-id, render-view-id, requestid) to a single ID which is passed |
| 21 // through rest of the speech code. | 21 // through rest of the speech code. |
| 22 class SpeechInputDispatcherHost::SpeechInputCallers { | 22 class SpeechRecognitionDispatcherHost::Callers { |
| 23 public: | 23 public: |
| 24 // Creates a new ID for a given tuple. | 24 // Creates a new ID for a given tuple. |
| 25 int CreateId(int render_process_id, int render_view_id, int request_id); | 25 int CreateId(int render_process_id, int render_view_id, int request_id); |
| 26 | 26 |
| 27 // Returns the ID for a tuple assuming the ID was created earlier. | 27 // Returns the ID for a tuple assuming the ID was created earlier. |
| 28 int GetId(int render_process_id, int render_view_id, int request_id); | 28 int GetId(int render_process_id, int render_view_id, int request_id); |
| 29 | 29 |
| 30 // Removes the ID and associated tuple from the map. | 30 // Removes the ID and associated tuple from the map. |
| 31 void RemoveId(int id); | 31 void RemoveId(int id); |
| 32 | 32 |
| 33 // Getters for the various tuple elements for the given ID. | 33 // Getters for the various tuple elements for the given ID. |
| 34 int render_process_id(int id); | 34 int render_process_id(int id); |
| 35 int render_view_id(int id); | 35 int render_view_id(int id); |
| 36 int request_id(int id); | 36 int request_id(int id); |
| 37 | 37 |
| 38 private: | 38 private: |
| 39 struct CallerInfo { | 39 struct CallerInfo { |
| 40 int render_process_id; | 40 int render_process_id; |
| 41 int render_view_id; | 41 int render_view_id; |
| 42 int request_id; | 42 int request_id; |
| 43 }; | 43 }; |
| 44 friend struct base::DefaultLazyInstanceTraits<SpeechInputCallers>; | 44 friend struct base::DefaultLazyInstanceTraits<Callers>; |
| 45 | 45 |
| 46 SpeechInputCallers(); | 46 Callers(); |
| 47 | 47 |
| 48 std::map<int, CallerInfo> callers_; | 48 std::map<int, CallerInfo> callers_; |
| 49 int next_id_; | 49 int next_id_; |
| 50 }; | 50 }; |
| 51 | 51 |
| 52 static base::LazyInstance<SpeechInputDispatcherHost::SpeechInputCallers> | 52 static base::LazyInstance<SpeechRecognitionDispatcherHost::Callers> |
| 53 g_speech_input_callers = LAZY_INSTANCE_INITIALIZER; | 53 g_callers = LAZY_INSTANCE_INITIALIZER; |
| 54 | 54 |
| 55 SpeechInputDispatcherHost::SpeechInputCallers::SpeechInputCallers() | 55 SpeechRecognitionDispatcherHost::Callers::Callers() |
| 56 : next_id_(1) { | 56 : next_id_(1) { |
| 57 } | 57 } |
| 58 | 58 |
| 59 int SpeechInputDispatcherHost::SpeechInputCallers::GetId(int render_process_id, | 59 int SpeechRecognitionDispatcherHost::Callers::GetId( |
| 60 int render_view_id, | 60 int render_process_id, |
| 61 int request_id) { | 61 int render_view_id, |
| 62 int request_id) { |
| 62 for (std::map<int, CallerInfo>::iterator it = callers_.begin(); | 63 for (std::map<int, CallerInfo>::iterator it = callers_.begin(); |
| 63 it != callers_.end(); it++) { | 64 it != callers_.end(); it++) { |
| 64 const CallerInfo& item = it->second; | 65 const CallerInfo& item = it->second; |
| 65 if (item.render_process_id == render_process_id && | 66 if (item.render_process_id == render_process_id && |
| 66 item.render_view_id == render_view_id && | 67 item.render_view_id == render_view_id && |
| 67 item.request_id == request_id) { | 68 item.request_id == request_id) { |
| 68 return it->first; | 69 return it->first; |
| 69 } | 70 } |
| 70 } | 71 } |
| 71 | 72 |
| 72 // Not finding an entry here is valid since a cancel/stop may have been issued | 73 // Not finding an entry here is valid since a cancel/stop may have been issued |
| 73 // by the renderer and before it received our response the user may have | 74 // by the renderer and before it received our response the user may have |
| 74 // clicked the button to stop again. The caller of this method should take | 75 // clicked the button to stop again. The caller of this method should take |
| 75 // care of this case. | 76 // care of this case. |
| 76 return 0; | 77 return 0; |
| 77 } | 78 } |
| 78 | 79 |
| 79 int SpeechInputDispatcherHost::SpeechInputCallers::CreateId( | 80 int SpeechRecognitionDispatcherHost::Callers::CreateId( |
| 80 int render_process_id, | 81 int render_process_id, |
| 81 int render_view_id, | 82 int render_view_id, |
| 82 int request_id) { | 83 int request_id) { |
| 83 CallerInfo info; | 84 CallerInfo info; |
| 84 info.render_process_id = render_process_id; | 85 info.render_process_id = render_process_id; |
| 85 info.render_view_id = render_view_id; | 86 info.render_view_id = render_view_id; |
| 86 info.request_id = request_id; | 87 info.request_id = request_id; |
| 87 callers_[next_id_] = info; | 88 callers_[next_id_] = info; |
| 88 return next_id_++; | 89 return next_id_++; |
| 89 } | 90 } |
| 90 | 91 |
| 91 void SpeechInputDispatcherHost::SpeechInputCallers::RemoveId(int id) { | 92 void SpeechRecognitionDispatcherHost::Callers::RemoveId(int id) { |
| 92 callers_.erase(id); | 93 callers_.erase(id); |
| 93 } | 94 } |
| 94 | 95 |
| 95 int SpeechInputDispatcherHost::SpeechInputCallers::render_process_id(int id) { | 96 int SpeechRecognitionDispatcherHost::Callers::render_process_id( |
| 97 int id) { |
| 96 return callers_[id].render_process_id; | 98 return callers_[id].render_process_id; |
| 97 } | 99 } |
| 98 | 100 |
| 99 int SpeechInputDispatcherHost::SpeechInputCallers::render_view_id(int id) { | 101 int SpeechRecognitionDispatcherHost::Callers::render_view_id( |
| 102 int id) { |
| 100 return callers_[id].render_view_id; | 103 return callers_[id].render_view_id; |
| 101 } | 104 } |
| 102 | 105 |
| 103 int SpeechInputDispatcherHost::SpeechInputCallers::request_id(int id) { | 106 int SpeechRecognitionDispatcherHost::Callers::request_id(int id) { |
| 104 return callers_[id].request_id; | 107 return callers_[id].request_id; |
| 105 } | 108 } |
| 106 | 109 |
| 107 //-------------------------- SpeechInputDispatcherHost ------------------------- | 110 //----------------------- SpeechRecognitionDispatcherHost ---------------------- |
| 108 | 111 |
| 109 SpeechInputManagerImpl* SpeechInputDispatcherHost::manager_; | 112 SpeechRecognitionManagerImpl* SpeechRecognitionDispatcherHost::manager_; |
| 110 | 113 |
| 111 void SpeechInputDispatcherHost::set_manager(SpeechInputManagerImpl* manager) { | 114 void SpeechRecognitionDispatcherHost::set_manager( |
| 115 SpeechRecognitionManagerImpl* manager) { |
| 112 manager_ = manager; | 116 manager_ = manager; |
| 113 } | 117 } |
| 114 | 118 |
| 115 SpeechInputDispatcherHost::SpeechInputDispatcherHost( | 119 SpeechRecognitionDispatcherHost::SpeechRecognitionDispatcherHost( |
| 116 int render_process_id, | 120 int render_process_id, |
| 117 net::URLRequestContextGetter* context_getter, | 121 net::URLRequestContextGetter* context_getter, |
| 118 content::SpeechInputPreferences* speech_input_preferences, | 122 content::SpeechRecognitionPreferences* recognition_preferences, |
| 119 AudioManager* audio_manager) | 123 AudioManager* audio_manager) |
| 120 : render_process_id_(render_process_id), | 124 : render_process_id_(render_process_id), |
| 121 may_have_pending_requests_(false), | 125 may_have_pending_requests_(false), |
| 122 context_getter_(context_getter), | 126 context_getter_(context_getter), |
| 123 speech_input_preferences_(speech_input_preferences), | 127 recognition_preferences_(recognition_preferences), |
| 124 audio_manager_(audio_manager) { | 128 audio_manager_(audio_manager) { |
| 125 // This is initialized by Browser. Do not add any non-trivial | 129 // This is initialized by Browser. Do not add any non-trivial |
| 126 // initialization here, instead do it lazily when required (e.g. see the | 130 // initialization here, instead do it lazily when required (e.g. see the |
| 127 // method |manager()|) or add an Init() method. | 131 // method |manager()|) or add an Init() method. |
| 128 } | 132 } |
| 129 | 133 |
| 130 SpeechInputDispatcherHost::~SpeechInputDispatcherHost() { | 134 SpeechRecognitionDispatcherHost::~SpeechRecognitionDispatcherHost() { |
| 131 // If the renderer crashed for some reason or if we didn't receive a proper | 135 // If the renderer crashed for some reason or if we didn't receive a proper |
| 132 // Cancel/Stop call for an existing session, cancel such active sessions now. | 136 // Cancel/Stop call for an existing session, cancel such active sessions now. |
| 133 // We first check if this dispatcher received any speech IPC requst so that | 137 // We first check if this dispatcher received any speech IPC requst so that |
| 134 // we don't end up creating the speech input manager for web pages which don't | 138 // we don't end up creating the speech input manager for web pages which don't |
| 135 // use speech input. | 139 // use speech input. |
| 136 if (may_have_pending_requests_) | 140 if (may_have_pending_requests_) |
| 137 manager()->CancelAllRequestsWithDelegate(this); | 141 manager()->CancelAllRequestsWithDelegate(this); |
| 138 } | 142 } |
| 139 | 143 |
| 140 SpeechInputManagerImpl* SpeechInputDispatcherHost::manager() { | 144 SpeechRecognitionManagerImpl* SpeechRecognitionDispatcherHost::manager() { |
| 141 if (manager_) | 145 if (manager_) |
| 142 return manager_; | 146 return manager_; |
| 143 #if defined(ENABLE_INPUT_SPEECH) | 147 #if defined(ENABLE_INPUT_SPEECH) |
| 144 return SpeechInputManagerImpl::GetInstance(); | 148 return SpeechRecognitionManagerImpl::GetInstance(); |
| 145 #else | 149 #else |
| 146 return NULL; | 150 return NULL; |
| 147 #endif | 151 #endif |
| 148 } | 152 } |
| 149 | 153 |
| 150 bool SpeechInputDispatcherHost::OnMessageReceived( | 154 bool SpeechRecognitionDispatcherHost::OnMessageReceived( |
| 151 const IPC::Message& message, bool* message_was_ok) { | 155 const IPC::Message& message, bool* message_was_ok) { |
| 152 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 156 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 153 bool handled = true; | 157 bool handled = true; |
| 154 IPC_BEGIN_MESSAGE_MAP_EX(SpeechInputDispatcherHost, message, | 158 IPC_BEGIN_MESSAGE_MAP_EX(SpeechRecognitionDispatcherHost, message, |
| 155 *message_was_ok) | 159 *message_was_ok) |
| 156 IPC_MESSAGE_HANDLER(SpeechInputHostMsg_StartRecognition, | 160 IPC_MESSAGE_HANDLER(SpeechRecognitionHostMsg_StartRequest, |
| 157 OnStartRecognition) | 161 OnStartRecognition) |
| 158 IPC_MESSAGE_HANDLER(SpeechInputHostMsg_CancelRecognition, | 162 IPC_MESSAGE_HANDLER(SpeechRecognitionHostMsg_AbortRequest, |
| 159 OnCancelRecognition) | 163 OnCancelRecognition) |
| 160 IPC_MESSAGE_HANDLER(SpeechInputHostMsg_StopRecording, | 164 IPC_MESSAGE_HANDLER(SpeechRecognitionHostMsg_StopAudioCaptureRequest, |
| 161 OnStopRecording) | 165 OnStopRecording) |
| 162 IPC_MESSAGE_UNHANDLED(handled = false) | 166 IPC_MESSAGE_UNHANDLED(handled = false) |
| 163 IPC_END_MESSAGE_MAP() | 167 IPC_END_MESSAGE_MAP() |
| 164 if (handled) | 168 if (handled) |
| 165 may_have_pending_requests_ = true; | 169 may_have_pending_requests_ = true; |
| 166 return handled; | 170 return handled; |
| 167 } | 171 } |
| 168 | 172 |
| 169 void SpeechInputDispatcherHost::OnStartRecognition( | 173 void SpeechRecognitionDispatcherHost::OnStartRecognition( |
| 170 const SpeechInputHostMsg_StartRecognition_Params ¶ms) { | 174 const SpeechRecognitionHostMsg_StartRequest_Params ¶ms) { |
| 171 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 175 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 172 int caller_id = g_speech_input_callers.Get().CreateId( | 176 int caller_id = g_callers.Get().CreateId( |
| 173 render_process_id_, params.render_view_id, params.request_id); | 177 render_process_id_, params.render_view_id, params.request_id); |
| 174 manager()->StartRecognition(this, caller_id, | 178 manager()->StartRecognition(this, caller_id, |
| 175 render_process_id_, | 179 render_process_id_, |
| 176 params.render_view_id, params.element_rect, | 180 params.render_view_id, params.element_rect, |
| 177 params.language, params.grammar, | 181 params.language, params.grammar, |
| 178 params.origin_url, | 182 params.origin_url, |
| 179 context_getter_.get(), | 183 context_getter_.get(), |
| 180 speech_input_preferences_.get()); | 184 recognition_preferences_.get()); |
| 181 } | 185 } |
| 182 | 186 |
| 183 void SpeechInputDispatcherHost::OnCancelRecognition(int render_view_id, | 187 void SpeechRecognitionDispatcherHost::OnCancelRecognition(int render_view_id, |
| 184 int request_id) { | 188 int request_id) { |
| 185 int caller_id = g_speech_input_callers.Get().GetId( | 189 int caller_id = g_callers.Get().GetId( |
| 186 render_process_id_, render_view_id, request_id); | 190 render_process_id_, render_view_id, request_id); |
| 187 if (caller_id) { | 191 if (caller_id) { |
| 188 manager()->CancelRecognition(caller_id); | 192 manager()->CancelRecognition(caller_id); |
| 189 // Request sequence ended so remove mapping. | 193 // Request sequence ended so remove mapping. |
| 190 g_speech_input_callers.Get().RemoveId(caller_id); | 194 g_callers.Get().RemoveId(caller_id); |
| 191 } | 195 } |
| 192 } | 196 } |
| 193 | 197 |
| 194 void SpeechInputDispatcherHost::OnStopRecording(int render_view_id, | 198 void SpeechRecognitionDispatcherHost::OnStopRecording(int render_view_id, |
| 195 int request_id) { | 199 int request_id) { |
| 196 int caller_id = g_speech_input_callers.Get().GetId( | 200 int caller_id = g_callers.Get().GetId( |
| 197 render_process_id_, render_view_id, request_id); | 201 render_process_id_, render_view_id, request_id); |
| 198 if (caller_id) | 202 if (caller_id) |
| 199 manager()->StopRecording(caller_id); | 203 manager()->StopRecording(caller_id); |
| 200 } | 204 } |
| 201 | 205 |
| 202 void SpeechInputDispatcherHost::SetRecognitionResult( | 206 void SpeechRecognitionDispatcherHost::SetRecognitionResult( |
| 203 int caller_id, const content::SpeechInputResult& result) { | 207 int caller_id, const content::SpeechInputResult& result) { |
| 204 VLOG(1) << "SpeechInputDispatcherHost::SetRecognitionResult enter"; | 208 VLOG(1) << "SpeechRecognitionDispatcherHost::SetRecognitionResult enter"; |
| 205 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 209 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 206 int caller_render_view_id = | 210 int caller_render_view_id = |
| 207 g_speech_input_callers.Get().render_view_id(caller_id); | 211 g_callers.Get().render_view_id(caller_id); |
| 208 int caller_request_id = g_speech_input_callers.Get().request_id(caller_id); | 212 int caller_request_id = g_callers.Get().request_id(caller_id); |
| 209 Send(new SpeechInputMsg_SetRecognitionResult(caller_render_view_id, | 213 Send(new SpeechRecognitionMsg_ResultRetrieved(caller_render_view_id, |
| 210 caller_request_id, | 214 caller_request_id, |
| 211 result)); | 215 result)); |
| 212 VLOG(1) << "SpeechInputDispatcherHost::SetRecognitionResult exit"; | 216 VLOG(1) << "SpeechRecognitionDispatcherHost::SetRecognitionResult exit"; |
| 213 } | 217 } |
| 214 | 218 |
| 215 void SpeechInputDispatcherHost::DidCompleteRecording(int caller_id) { | 219 void SpeechRecognitionDispatcherHost::DidCompleteRecording(int caller_id) { |
| 216 VLOG(1) << "SpeechInputDispatcherHost::DidCompleteRecording enter"; | 220 VLOG(1) << "SpeechRecognitionDispatcherHost::DidCompleteRecording enter"; |
| 217 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 221 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 218 int caller_render_view_id = | 222 int caller_render_view_id = |
| 219 g_speech_input_callers.Get().render_view_id(caller_id); | 223 g_callers.Get().render_view_id(caller_id); |
| 220 int caller_request_id = g_speech_input_callers.Get().request_id(caller_id); | 224 int caller_request_id = g_callers.Get().request_id(caller_id); |
| 221 Send(new SpeechInputMsg_RecordingComplete(caller_render_view_id, | 225 Send(new SpeechRecognitionMsg_AudioEnded(caller_render_view_id, |
| 222 caller_request_id)); | 226 caller_request_id)); |
| 223 VLOG(1) << "SpeechInputDispatcherHost::DidCompleteRecording exit"; | 227 VLOG(1) << "SpeechRecognitionDispatcherHost::DidCompleteRecording exit"; |
| 224 } | 228 } |
| 225 | 229 |
| 226 void SpeechInputDispatcherHost::DidCompleteRecognition(int caller_id) { | 230 void SpeechRecognitionDispatcherHost::DidCompleteRecognition(int caller_id) { |
| 227 VLOG(1) << "SpeechInputDispatcherHost::DidCompleteRecognition enter"; | 231 VLOG(1) << "SpeechRecognitionDispatcherHost::DidCompleteRecognition enter"; |
| 228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 232 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 229 int caller_render_view_id = | 233 int caller_render_view_id = |
| 230 g_speech_input_callers.Get().render_view_id(caller_id); | 234 g_callers.Get().render_view_id(caller_id); |
| 231 int caller_request_id = g_speech_input_callers.Get().request_id(caller_id); | 235 int caller_request_id = g_callers.Get().request_id(caller_id); |
| 232 Send(new SpeechInputMsg_RecognitionComplete(caller_render_view_id, | 236 Send(new SpeechRecognitionMsg_RecognitionEnded(caller_render_view_id, |
| 233 caller_request_id)); | 237 caller_request_id)); |
| 234 // Request sequence ended, so remove mapping. | 238 // Request sequence ended, so remove mapping. |
| 235 g_speech_input_callers.Get().RemoveId(caller_id); | 239 g_callers.Get().RemoveId(caller_id); |
| 236 VLOG(1) << "SpeechInputDispatcherHost::DidCompleteRecognition exit"; | 240 VLOG(1) << "SpeechRecognitionDispatcherHost::DidCompleteRecognition exit"; |
| 237 } | 241 } |
| 238 | 242 |
| 239 } // namespace speech_input | 243 } // namespace speech |
| OLD | NEW |