Chromium Code Reviews| 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 "chrome/browser/speech/chrome_speech_recognition_manager_delegate.h" | 5 #include "chrome/browser/speech/chrome_speech_recognition_manager_delegate.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/synchronization/lock.h" | 10 #include "base/synchronization/lock.h" |
| 11 #include "base/threading/thread_restrictions.h" | 11 #include "base/threading/thread_restrictions.h" |
| 12 #include "base/utf_string_conversions.h" | 12 #include "base/utf_string_conversions.h" |
| 13 #include "chrome/browser/browser_process.h" | 13 #include "chrome/browser/browser_process.h" |
| 14 #include "chrome/browser/prefs/pref_service.h" | 14 #include "chrome/browser/prefs/pref_service.h" |
| 15 #include "chrome/browser/profiles/profile_manager.h" | 15 #include "chrome/browser/profiles/profile_manager.h" |
| 16 #include "chrome/browser/speech/speech_recognition_tray_icon_controller.h" | |
| 16 #include "chrome/browser/tab_contents/tab_util.h" | 17 #include "chrome/browser/tab_contents/tab_util.h" |
| 17 #include "chrome/common/chrome_view_type.h" | 18 #include "chrome/common/chrome_view_type.h" |
| 18 #include "chrome/common/pref_names.h" | 19 #include "chrome/common/pref_names.h" |
| 19 #include "content/public/browser/browser_thread.h" | 20 #include "content/public/browser/browser_thread.h" |
| 20 #include "content/public/browser/render_view_host.h" | 21 #include "content/public/browser/render_view_host.h" |
| 21 #include "content/public/browser/render_view_host_delegate.h" | 22 #include "content/public/browser/render_view_host_delegate.h" |
| 22 #include "content/public/browser/resource_context.h" | 23 #include "content/public/browser/resource_context.h" |
| 23 #include "content/public/browser/speech_recognition_manager.h" | 24 #include "content/public/browser/speech_recognition_manager.h" |
| 24 #include "content/public/browser/speech_recognition_session_config.h" | 25 #include "content/public/browser/speech_recognition_session_config.h" |
| 25 #include "content/public/browser/speech_recognition_session_context.h" | 26 #include "content/public/browser/speech_recognition_session_context.h" |
| 26 #include "content/public/common/speech_recognition_error.h" | 27 #include "content/public/common/speech_recognition_error.h" |
| 27 #include "content/public/common/speech_recognition_result.h" | 28 #include "content/public/common/speech_recognition_result.h" |
| 28 #include "grit/generated_resources.h" | 29 #include "grit/generated_resources.h" |
| 29 #include "net/url_request/url_request_context_getter.h" | 30 #include "net/url_request/url_request_context_getter.h" |
| 30 #include "ui/base/l10n/l10n_util.h" | 31 #include "ui/base/l10n/l10n_util.h" |
| 31 | 32 |
| 32 #if defined(OS_WIN) | 33 #if defined(OS_WIN) |
| 33 #include "chrome/installer/util/wmi.h" | 34 #include "chrome/installer/util/wmi.h" |
| 34 #endif | 35 #endif |
| 35 | 36 |
| 36 using content::BrowserThread; | 37 using content::BrowserThread; |
| 37 using content::SpeechRecognitionManager; | 38 using content::SpeechRecognitionManager; |
| 39 using content::SpeechRecognitionSessionContext; | |
| 38 | 40 |
| 39 namespace { | 41 namespace { |
| 40 const int kNoActiveBubble = | 42 const int kNoActiveBubble = |
| 41 content::SpeechRecognitionManager::kSessionIDInvalid; | 43 content::SpeechRecognitionManager::kSessionIDInvalid; |
| 44 | |
| 45 bool IsRequiredBubble(int session_id) { | |
| 46 return SpeechRecognitionManager::GetInstance()-> | |
| 47 GetSessionContext(session_id).use_bubble_on_element; | |
| 48 } | |
| 49 | |
| 50 bool IsRequiredTrayIcon(int session_id) { | |
|
hans
2012/05/15 13:35:17
these names (this and IsRequiredBubble) aren't gre
Primiano Tucci (use gerrit)
2012/05/16 10:16:00
Done.
| |
| 51 return !IsRequiredBubble(session_id); | |
| 52 } | |
| 42 } // namespace | 53 } // namespace |
| 43 | 54 |
| 44 namespace speech { | 55 namespace speech { |
| 45 | 56 |
| 46 // Asynchronously fetches the PC and audio hardware/driver info if | 57 // Asynchronously fetches the PC and audio hardware/driver info if |
| 47 // the user has opted into UMA. This information is sent with speech input | 58 // the user has opted into UMA. This information is sent with speech input |
| 48 // requests to the server for identifying and improving quality issues with | 59 // requests to the server for identifying and improving quality issues with |
| 49 // specific device configurations. | 60 // specific device configurations. |
| 50 class ChromeSpeechRecognitionManagerDelegate::OptionalRequestInfo | 61 class ChromeSpeechRecognitionManagerDelegate::OptionalRequestInfo |
| 51 : public base::RefCountedThreadSafe<OptionalRequestInfo> { | 62 : public base::RefCountedThreadSafe<OptionalRequestInfo> { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 100 ~OptionalRequestInfo() {} | 111 ~OptionalRequestInfo() {} |
| 101 | 112 |
| 102 base::Lock lock_; | 113 base::Lock lock_; |
| 103 std::string value_; | 114 std::string value_; |
| 104 bool can_report_metrics_; | 115 bool can_report_metrics_; |
| 105 | 116 |
| 106 DISALLOW_COPY_AND_ASSIGN(OptionalRequestInfo); | 117 DISALLOW_COPY_AND_ASSIGN(OptionalRequestInfo); |
| 107 }; | 118 }; |
| 108 | 119 |
| 109 ChromeSpeechRecognitionManagerDelegate::ChromeSpeechRecognitionManagerDelegate() | 120 ChromeSpeechRecognitionManagerDelegate::ChromeSpeechRecognitionManagerDelegate() |
| 110 : bubble_controller_(new SpeechRecognitionBubbleController( | 121 : active_bubble_session_id_(kNoActiveBubble) { |
| 111 ALLOW_THIS_IN_INITIALIZER_LIST(this))), | |
| 112 active_bubble_session_id_(kNoActiveBubble) { | |
| 113 SpeechRecognitionManager::GetInstance()->SetDelegate(this); | 122 SpeechRecognitionManager::GetInstance()->SetDelegate(this); |
| 114 } | 123 } |
| 115 | 124 |
| 116 ChromeSpeechRecognitionManagerDelegate:: | 125 ChromeSpeechRecognitionManagerDelegate:: |
| 117 ~ChromeSpeechRecognitionManagerDelegate() { | 126 ~ChromeSpeechRecognitionManagerDelegate() { |
| 118 SpeechRecognitionManager::GetInstance()->SetDelegate(NULL); | 127 SpeechRecognitionManager::GetInstance()->SetDelegate(NULL); |
| 128 if (tray_icon_controller_.get()) | |
| 129 tray_icon_controller_->Hide(); | |
| 119 if (active_bubble_session_id_ != kNoActiveBubble) { | 130 if (active_bubble_session_id_ != kNoActiveBubble) { |
| 120 DCHECK(bubble_controller_.get()); | 131 DCHECK(bubble_controller_.get()); |
| 121 bubble_controller_->CloseBubble(active_bubble_session_id_); | 132 bubble_controller_->CloseBubble(active_bubble_session_id_); |
| 122 } | 133 } |
| 123 } | 134 } |
| 124 | 135 |
| 125 void ChromeSpeechRecognitionManagerDelegate::InfoBubbleButtonClicked( | 136 void ChromeSpeechRecognitionManagerDelegate::InfoBubbleButtonClicked( |
| 126 int session_id, SpeechRecognitionBubble::Button button) { | 137 int session_id, SpeechRecognitionBubble::Button button) { |
| 127 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 138 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 128 DCHECK_EQ(active_bubble_session_id_, session_id); | 139 DCHECK_EQ(active_bubble_session_id_, session_id); |
| 129 | 140 |
| 141 // Note, the session might have been destroyed, therefore avoid calls to the | |
| 142 // manager which imply its existance (e.g., GetSessionContext()). | |
| 143 | |
| 130 if (button == SpeechRecognitionBubble::BUTTON_CANCEL) { | 144 if (button == SpeechRecognitionBubble::BUTTON_CANCEL) { |
| 131 bubble_controller_->CloseBubble(session_id); | 145 BubbleController()->CloseBubble(session_id); |
| 132 last_session_config_.reset(); | 146 last_session_config_.reset(); |
| 133 active_bubble_session_id_ = kNoActiveBubble; | 147 active_bubble_session_id_ = kNoActiveBubble; |
| 134 | 148 |
| 135 // We can safely call AbortSession even if the session has already ended, | 149 // We can safely call AbortSession even if the session has already ended, |
| 136 // the manager's public methods are reliable and will handle it properly. | 150 // the manager's public methods are reliable and will handle it properly. |
| 137 SpeechRecognitionManager::GetInstance()->AbortSession(session_id); | 151 SpeechRecognitionManager::GetInstance()->AbortSession(session_id); |
| 138 } else if (button == SpeechRecognitionBubble::BUTTON_TRY_AGAIN) { | 152 } else if (button == SpeechRecognitionBubble::BUTTON_TRY_AGAIN) { |
| 139 bubble_controller_->CloseBubble(session_id); | 153 BubbleController()->CloseBubble(session_id); |
| 140 active_bubble_session_id_ = kNoActiveBubble; | 154 active_bubble_session_id_ = kNoActiveBubble; |
| 141 RestartLastSession(); | 155 RestartLastSession(); |
| 142 } | 156 } |
| 143 } | 157 } |
| 144 | 158 |
| 145 void ChromeSpeechRecognitionManagerDelegate::InfoBubbleFocusChanged( | 159 void ChromeSpeechRecognitionManagerDelegate::InfoBubbleFocusChanged( |
| 146 int session_id) { | 160 int session_id) { |
| 147 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 161 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 148 DCHECK_EQ(active_bubble_session_id_, session_id); | 162 DCHECK_EQ(active_bubble_session_id_, session_id); |
| 149 | 163 |
| 150 bubble_controller_->CloseBubble(session_id); | 164 // Note, the session might have been destroyed (see InfoBubbleButtonClicked). |
| 165 | |
| 166 BubbleController()->CloseBubble(session_id); | |
| 151 last_session_config_.reset(); | 167 last_session_config_.reset(); |
| 152 active_bubble_session_id_ = kNoActiveBubble; | 168 active_bubble_session_id_ = kNoActiveBubble; |
| 153 | 169 |
| 154 // If the user clicks outside the bubble while capturing audio we abort the | 170 // If the user clicks outside the bubble while capturing audio we abort the |
| 155 // session. Otherwise, i.e. audio capture is ended and we are just waiting for | 171 // session. Otherwise, i.e. audio capture is ended and we are just waiting for |
| 156 // results, this activity is carried silently in background. | 172 // results, this activity is carried silently in background. |
| 157 if (SpeechRecognitionManager::GetInstance()->IsCapturingAudio()) | 173 if (SpeechRecognitionManager::GetInstance()->IsCapturingAudio()) |
| 158 SpeechRecognitionManager::GetInstance()->AbortSession(session_id); | 174 SpeechRecognitionManager::GetInstance()->AbortSession(session_id); |
| 159 } | 175 } |
| 160 | 176 |
| 161 void ChromeSpeechRecognitionManagerDelegate::RestartLastSession() { | 177 void ChromeSpeechRecognitionManagerDelegate::RestartLastSession() { |
| 162 DCHECK(last_session_config_.get()); | 178 DCHECK(last_session_config_.get()); |
| 163 SpeechRecognitionManager* manager = SpeechRecognitionManager::GetInstance(); | 179 SpeechRecognitionManager* manager = SpeechRecognitionManager::GetInstance(); |
| 164 const int new_session_id = manager->CreateSession(*last_session_config_); | 180 const int new_session_id = manager->CreateSession(*last_session_config_); |
| 165 DCHECK_NE(new_session_id, kNoActiveBubble); | 181 DCHECK_NE(new_session_id, kNoActiveBubble); |
| 166 last_session_config_.reset(); | 182 last_session_config_.reset(); |
| 167 manager->StartSession(new_session_id); | 183 manager->StartSession(new_session_id); |
| 168 } | 184 } |
| 169 | 185 |
| 170 void ChromeSpeechRecognitionManagerDelegate::OnRecognitionStart( | 186 void ChromeSpeechRecognitionManagerDelegate::OnRecognitionStart( |
| 171 int session_id) { | 187 int session_id) { |
| 172 // Copy the configuration of the session (for the "try again" button). | 188 SpeechRecognitionManager* manager = SpeechRecognitionManager::GetInstance(); |
| 173 last_session_config_.reset(new content::SpeechRecognitionSessionConfig( | 189 const content::SpeechRecognitionSessionContext& context = |
| 174 SpeechRecognitionManager::GetInstance()->GetSessionConfig(session_id))); | 190 manager->GetSessionContext(session_id); |
| 175 | 191 |
| 176 // Create and show the bubble. | 192 if (IsRequiredBubble(session_id)) { |
| 177 DCHECK_EQ(active_bubble_session_id_, kNoActiveBubble); | 193 // Copy the configuration of the session (for the "try again" button). |
| 178 active_bubble_session_id_ = session_id; | 194 last_session_config_.reset(new content::SpeechRecognitionSessionConfig( |
| 179 const content::SpeechRecognitionSessionContext& context = | 195 manager->GetSessionConfig(session_id))); |
| 180 SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id); | 196 |
| 181 bubble_controller_->CreateBubble(session_id, | 197 // Create and show the bubble. |
| 182 context.render_process_id, | 198 DCHECK_EQ(active_bubble_session_id_, kNoActiveBubble); |
| 183 context.render_view_id, | 199 active_bubble_session_id_ = session_id; |
| 184 context.element_rect); | 200 BubbleController()->CreateBubble(session_id, |
| 185 // TODO(primiano) Why not create directly the bubble in warmup mode? | 201 context.render_process_id, |
| 186 bubble_controller_->SetBubbleWarmUpMode(session_id); | 202 context.render_view_id, |
| 203 context.element_rect); | |
| 204 | |
| 205 // TODO(primiano) Why not creating directly the bubble in warmup mode? | |
| 206 BubbleController()->SetBubbleWarmUpMode(session_id); | |
| 207 } else if (IsRequiredTrayIcon(session_id)) { | |
| 208 TrayIconController()->Show(context.context_name, | |
| 209 context.show_security_balloon); | |
| 210 } | |
| 187 } | 211 } |
| 188 | 212 |
| 189 void ChromeSpeechRecognitionManagerDelegate::OnAudioStart(int session_id) { | 213 void ChromeSpeechRecognitionManagerDelegate::OnAudioStart(int session_id) { |
| 190 bubble_controller_->SetBubbleRecordingMode(session_id); | 214 if (IsRequiredBubble(session_id)) |
| 215 BubbleController()->SetBubbleRecordingMode(session_id); | |
| 191 } | 216 } |
| 192 | 217 |
| 193 void ChromeSpeechRecognitionManagerDelegate::OnEnvironmentEstimationComplete( | 218 void ChromeSpeechRecognitionManagerDelegate::OnEnvironmentEstimationComplete( |
| 194 int session_id) { | 219 int session_id) { |
| 195 } | 220 } |
| 196 | 221 |
| 197 void ChromeSpeechRecognitionManagerDelegate::OnSoundStart(int session_id) { | 222 void ChromeSpeechRecognitionManagerDelegate::OnSoundStart(int session_id) { |
| 198 } | 223 } |
| 199 | 224 |
| 200 void ChromeSpeechRecognitionManagerDelegate::OnSoundEnd(int session_id) { | 225 void ChromeSpeechRecognitionManagerDelegate::OnSoundEnd(int session_id) { |
| 201 } | 226 } |
| 202 | 227 |
| 203 void ChromeSpeechRecognitionManagerDelegate::OnAudioEnd(int session_id) { | 228 void ChromeSpeechRecognitionManagerDelegate::OnAudioEnd(int session_id) { |
| 204 // OnAudioEnd can be also raised after an abort, when the bubble has already | 229 // OnAudioEnd can be also raised after an abort, when the bubble has already |
| 205 // been closed. | 230 // been closed. |
| 206 if (active_bubble_session_id_ == session_id) | 231 if (IsRequiredBubble(session_id) && active_bubble_session_id_ == session_id) |
| 207 bubble_controller_->SetBubbleRecognizingMode(session_id); | 232 BubbleController()->SetBubbleRecognizingMode(session_id); |
| 208 } | 233 } |
| 209 | 234 |
| 210 void ChromeSpeechRecognitionManagerDelegate::OnRecognitionResult( | 235 void ChromeSpeechRecognitionManagerDelegate::OnRecognitionResult( |
| 211 int session_id, const content::SpeechRecognitionResult& result) { | 236 int session_id, const content::SpeechRecognitionResult& result) { |
| 212 // A result can be dispatched when the bubble is not visible anymore (e.g., | 237 // A result can be dispatched when the bubble is not visible anymore (e.g., |
| 213 // lost focus while waiting for a result, thus continuing in background). | 238 // lost focus while waiting for a result, thus continuing in background). |
| 214 if (active_bubble_session_id_ == session_id) { | 239 if (IsRequiredBubble(session_id) && active_bubble_session_id_ == session_id) { |
| 215 bubble_controller_->CloseBubble(session_id); | 240 BubbleController()->CloseBubble(session_id); |
| 216 last_session_config_.reset(); | 241 last_session_config_.reset(); |
| 217 active_bubble_session_id_ = kNoActiveBubble; | 242 active_bubble_session_id_ = kNoActiveBubble; |
| 218 } | 243 } |
| 219 } | 244 } |
| 220 | 245 |
| 221 void ChromeSpeechRecognitionManagerDelegate::OnRecognitionError( | 246 void ChromeSpeechRecognitionManagerDelegate::OnRecognitionError( |
| 222 int session_id, const content::SpeechRecognitionError& error) { | 247 int session_id, const content::SpeechRecognitionError& error) { |
| 223 // An error can be dispatched when the bubble is not visible anymore. | 248 // An error can be dispatched when the bubble is not visible anymore. |
| 224 if (active_bubble_session_id_ != session_id) | 249 if (active_bubble_session_id_ != session_id) |
| 225 return; | 250 return; |
| 251 DCHECK(IsRequiredBubble(session_id)); | |
| 226 | 252 |
| 227 int error_message_id = 0; | 253 int error_message_id = 0; |
| 228 switch (error.code) { | 254 switch (error.code) { |
| 229 case content::SPEECH_RECOGNITION_ERROR_AUDIO: | 255 case content::SPEECH_RECOGNITION_ERROR_AUDIO: |
| 230 switch (error.details) { | 256 switch (error.details) { |
| 231 case content::SPEECH_AUDIO_ERROR_DETAILS_NO_MIC: | 257 case content::SPEECH_AUDIO_ERROR_DETAILS_NO_MIC: |
| 232 error_message_id = IDS_SPEECH_INPUT_NO_MIC; | 258 error_message_id = IDS_SPEECH_INPUT_NO_MIC; |
| 233 break; | 259 break; |
| 234 case content::SPEECH_AUDIO_ERROR_DETAILS_IN_USE: | 260 case content::SPEECH_AUDIO_ERROR_DETAILS_IN_USE: |
| 235 error_message_id = IDS_SPEECH_INPUT_MIC_IN_USE; | 261 error_message_id = IDS_SPEECH_INPUT_MIC_IN_USE; |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 248 case content::SPEECH_RECOGNITION_ERROR_NO_MATCH: | 274 case content::SPEECH_RECOGNITION_ERROR_NO_MATCH: |
| 249 error_message_id = IDS_SPEECH_INPUT_NO_RESULTS; | 275 error_message_id = IDS_SPEECH_INPUT_NO_RESULTS; |
| 250 break; | 276 break; |
| 251 case content::SPEECH_RECOGNITION_ERROR_NETWORK: | 277 case content::SPEECH_RECOGNITION_ERROR_NETWORK: |
| 252 error_message_id = IDS_SPEECH_INPUT_NET_ERROR; | 278 error_message_id = IDS_SPEECH_INPUT_NET_ERROR; |
| 253 break; | 279 break; |
| 254 default: | 280 default: |
| 255 NOTREACHED() << "unknown error " << error.code; | 281 NOTREACHED() << "unknown error " << error.code; |
| 256 return; | 282 return; |
| 257 } | 283 } |
| 258 bubble_controller_->SetBubbleMessage( | 284 BubbleController()->SetBubbleMessage( |
| 259 session_id, l10n_util::GetStringUTF16(error_message_id)); | 285 session_id, l10n_util::GetStringUTF16(error_message_id)); |
| 260 } | 286 } |
| 261 | 287 |
| 262 void ChromeSpeechRecognitionManagerDelegate::OnAudioLevelsChange( | 288 void ChromeSpeechRecognitionManagerDelegate::OnAudioLevelsChange( |
| 263 int session_id, float volume, float noise_volume) { | 289 int session_id, float volume, float noise_volume) { |
| 264 if (active_bubble_session_id_ == session_id) | 290 if (active_bubble_session_id_ == session_id) { |
| 265 bubble_controller_->SetBubbleInputVolume(session_id, volume, noise_volume); | 291 DCHECK(IsRequiredBubble(session_id)); |
| 292 BubbleController()->SetBubbleInputVolume(session_id, volume, noise_volume); | |
| 293 } else if (IsRequiredTrayIcon(session_id)) { | |
| 294 TrayIconController()->SetVUMeterVolume(volume); | |
| 295 } | |
| 266 } | 296 } |
| 267 | 297 |
| 268 void ChromeSpeechRecognitionManagerDelegate::OnRecognitionEnd(int session_id) { | 298 void ChromeSpeechRecognitionManagerDelegate::OnRecognitionEnd(int session_id) { |
| 299 if (IsRequiredTrayIcon(session_id)) | |
| 300 TrayIconController()->Hide(); | |
| 301 // No need to remove the bubble here, since: | |
| 302 // - A previous OnRecognitionResult event already closed the bubble. | |
| 303 // - An error occurred, so the bubble is showing the error and will be closed | |
| 304 // when it will lose focus (by InfoBubbleFocusChanged()). | |
| 305 // - The bubble lost focus or the user pressed the Cancel button, thus it has | |
| 306 // been closed by InfoBubbleFocusChanged(), which triggered an AbortSession. | |
|
hans
2012/05/15 13:35:17
so could we add a DCHECK that the bubble is closed
Primiano Tucci (use gerrit)
2012/05/16 10:16:00
I am afraid not. See point 2 in the code comment.
| |
| 269 } | 307 } |
| 270 | 308 |
| 271 void ChromeSpeechRecognitionManagerDelegate::GetDiagnosticInformation( | 309 void ChromeSpeechRecognitionManagerDelegate::GetDiagnosticInformation( |
| 272 bool* can_report_metrics, | 310 bool* can_report_metrics, |
| 273 std::string* hardware_info) { | 311 std::string* hardware_info) { |
| 274 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 312 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 275 if (!optional_request_info_.get()) { | 313 if (!optional_request_info_.get()) { |
| 276 optional_request_info_ = new OptionalRequestInfo(); | 314 optional_request_info_ = new OptionalRequestInfo(); |
| 277 // Since hardware info is optional with speech input requests, we start an | 315 // Since hardware info is optional with speech input requests, we start an |
| 278 // asynchronous fetch here and move on with recording audio. This first | 316 // asynchronous fetch here and move on with recording audio. This first |
| 279 // speech input request would send an empty string for hardware info and | 317 // speech input request would send an empty string for hardware info and |
| 280 // subsequent requests may have the hardware info available if the fetch | 318 // subsequent requests may have the hardware info available if the fetch |
| 281 // completed before them. This way we don't end up stalling the user with | 319 // completed before them. This way we don't end up stalling the user with |
| 282 // a long wait and disk seeks when they click on a UI element and start | 320 // a long wait and disk seeks when they click on a UI element and start |
| 283 // speaking. | 321 // speaking. |
| 284 optional_request_info_->Refresh(); | 322 optional_request_info_->Refresh(); |
| 285 } | 323 } |
| 286 *can_report_metrics = optional_request_info_->can_report_metrics(); | 324 *can_report_metrics = optional_request_info_->can_report_metrics(); |
| 287 *hardware_info = optional_request_info_->value(); | 325 *hardware_info = optional_request_info_->value(); |
| 288 } | 326 } |
| 289 | 327 |
| 290 void ChromeSpeechRecognitionManagerDelegate::CheckRecognitionIsAllowed( | 328 void ChromeSpeechRecognitionManagerDelegate::CheckRecognitionIsAllowed( |
| 291 int session_id, | 329 int session_id, |
| 292 base::Callback<void(int session_id, bool is_allowed)> callback) { | 330 base::Callback<void(int session_id, bool is_allowed)> callback) { |
| 293 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 331 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 332 | |
| 333 // We don't need any particular check for sessions not using a bubble. In such | |
| 334 // cases, we just notify it to the manager (calling-back synchronously, since | |
| 335 // we remain in the IO thread). | |
| 336 if (IsRequiredTrayIcon(session_id)) { | |
| 337 callback.Run(session_id, true /* is_allowed */); | |
| 338 return; | |
| 339 } | |
| 340 | |
| 341 // Sessions using bubbles, conversely, need a check on the renderer view type. | |
| 342 // The check must be performed in the UI thread. We defer it posting to | |
| 343 // CheckRenderViewType, which will issue the callback on our behalf. | |
| 294 const content::SpeechRecognitionSessionContext& context = | 344 const content::SpeechRecognitionSessionContext& context = |
| 295 SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id); | 345 SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id); |
| 296 | |
| 297 // The check must be performed in the UI thread. We defer it posting to | |
| 298 // CheckRenderViewType, which will issue the callback on our behalf. | |
| 299 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 346 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 300 base::Bind(&CheckRenderViewType, | 347 base::Bind(&CheckRenderViewType, |
| 301 session_id, | 348 session_id, |
| 302 callback, | 349 callback, |
| 303 context.render_process_id, | 350 context.render_process_id, |
| 304 context.render_view_id)); | 351 context.render_view_id)); |
| 305 } | 352 } |
| 306 | 353 |
| 307 content::SpeechRecognitionEventListener* | 354 content::SpeechRecognitionEventListener* |
| 308 ChromeSpeechRecognitionManagerDelegate::GetEventListener() { | 355 ChromeSpeechRecognitionManagerDelegate::GetEventListener() { |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 326 // speech input extension API should be used instead. | 373 // speech input extension API should be used instead. |
| 327 | 374 |
| 328 const bool allowed = (render_view_host != NULL && | 375 const bool allowed = (render_view_host != NULL && |
| 329 render_view_host->GetDelegate() != NULL && | 376 render_view_host->GetDelegate() != NULL && |
| 330 render_view_host->GetDelegate()->GetRenderViewType() == | 377 render_view_host->GetDelegate()->GetRenderViewType() == |
| 331 chrome::VIEW_TYPE_TAB_CONTENTS); | 378 chrome::VIEW_TYPE_TAB_CONTENTS); |
| 332 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 379 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| 333 base::Bind(callback, session_id, allowed)); | 380 base::Bind(callback, session_id, allowed)); |
| 334 } | 381 } |
| 335 | 382 |
| 383 SpeechRecognitionBubbleController* | |
| 384 ChromeSpeechRecognitionManagerDelegate::BubbleController() { | |
| 385 if (!bubble_controller_.get()) | |
| 386 bubble_controller_ = new SpeechRecognitionBubbleController(this); | |
| 387 return bubble_controller_.get(); | |
| 388 } | |
| 389 | |
| 390 SpeechRecognitionTrayIconController* | |
| 391 ChromeSpeechRecognitionManagerDelegate::TrayIconController() { | |
| 392 if (!tray_icon_controller_.get()) | |
| 393 tray_icon_controller_ = new SpeechRecognitionTrayIconController(); | |
| 394 return tray_icon_controller_.get(); | |
| 395 } | |
| 396 | |
| 397 | |
| 336 } // namespace speech | 398 } // namespace speech |
| OLD | NEW |