| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/speech_input_manager.h" | 5 #include "chrome/browser/speech/speech_input_manager.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "app/l10n_util.h" | 10 #include "app/l10n_util.h" |
| 11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 12 #include "base/lazy_instance.h" | 12 #include "base/lazy_instance.h" |
| 13 #include "base/lock.h" | 13 #include "base/lock.h" |
| 14 #include "base/ref_counted.h" | 14 #include "base/ref_counted.h" |
| 15 #include "base/threading/thread_restrictions.h" | 15 #include "base/threading/thread_restrictions.h" |
| 16 #include "base/utf_string_conversions.h" | 16 #include "base/utf_string_conversions.h" |
| 17 #include "chrome/browser/browser_process.h" |
| 17 #include "chrome/browser/browser_thread.h" | 18 #include "chrome/browser/browser_thread.h" |
| 18 #include "chrome/browser/platform_util.h" | 19 #include "chrome/browser/platform_util.h" |
| 19 #include "chrome/browser/prefs/pref_service.h" | 20 #include "chrome/browser/prefs/pref_service.h" |
| 20 #include "chrome/browser/speech/speech_input_bubble_controller.h" | 21 #include "chrome/browser/speech/speech_input_bubble_controller.h" |
| 21 #include "chrome/browser/speech/speech_recognizer.h" | 22 #include "chrome/browser/speech/speech_recognizer.h" |
| 22 #include "chrome/browser/tab_contents/infobar_delegate.h" | 23 #include "chrome/browser/tab_contents/infobar_delegate.h" |
| 23 #include "chrome/browser/tab_contents/tab_util.h" | 24 #include "chrome/browser/tab_contents/tab_util.h" |
| 24 #include "chrome/common/chrome_switches.h" | 25 #include "chrome/common/chrome_switches.h" |
| 25 #include "chrome/common/pref_names.h" | 26 #include "chrome/common/pref_names.h" |
| 26 #include "grit/generated_resources.h" | 27 #include "grit/generated_resources.h" |
| 27 #include "media/audio/audio_manager.h" | 28 #include "media/audio/audio_manager.h" |
| 28 | 29 |
| 29 #if defined(OS_WIN) | 30 #if defined(OS_WIN) |
| 30 #include "chrome/browser/browser_process.h" | |
| 31 #include "chrome/installer/util/wmi.h" | 31 #include "chrome/installer/util/wmi.h" |
| 32 #endif | 32 #endif |
| 33 | 33 |
| 34 namespace { | 34 namespace { |
| 35 | 35 |
| 36 // Asynchronously fetches the PC and audio hardware/driver info on windows if | 36 // Asynchronously fetches the PC and audio hardware/driver info if |
| 37 // the user has opted into UMA. This information is sent with speech input | 37 // the user has opted into UMA. This information is sent with speech input |
| 38 // requests to the server for identifying and improving quality issues with | 38 // requests to the server for identifying and improving quality issues with |
| 39 // specific device configurations. | 39 // specific device configurations. |
| 40 class HardwareInfo : public base::RefCountedThreadSafe<HardwareInfo> { | 40 class OptionalRequestInfo |
| 41 : public base::RefCountedThreadSafe<OptionalRequestInfo> { |
| 41 public: | 42 public: |
| 42 HardwareInfo() {} | 43 OptionalRequestInfo() : can_report_metrics_(false) {} |
| 43 | 44 |
| 44 #if defined(OS_WIN) | |
| 45 void Refresh() { | 45 void Refresh() { |
| 46 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 46 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 47 // UMA opt-in can be checked only from the UI thread, so switch to that. | 47 // UMA opt-in can be checked only from the UI thread, so switch to that. |
| 48 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 48 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 49 NewRunnableMethod(this, &HardwareInfo::CheckUMAAndGetHardwareInfo)); | 49 NewRunnableMethod(this, |
| 50 &OptionalRequestInfo::CheckUMAAndGetHardwareInfo)); |
| 50 } | 51 } |
| 51 | 52 |
| 52 void CheckUMAAndGetHardwareInfo() { | 53 void CheckUMAAndGetHardwareInfo() { |
| 53 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 54 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 54 if (g_browser_process->local_state()->GetBoolean( | 55 if (g_browser_process->local_state()->GetBoolean( |
| 55 prefs::kMetricsReportingEnabled)) { | 56 prefs::kMetricsReportingEnabled)) { |
| 56 // Access potentially slow OS calls from the FILE thread. | 57 // Access potentially slow OS calls from the FILE thread. |
| 57 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 58 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
| 58 NewRunnableMethod(this, &HardwareInfo::GetHardwareInfo)); | 59 NewRunnableMethod(this, &OptionalRequestInfo::GetHardwareInfo)); |
| 59 } | 60 } |
| 60 } | 61 } |
| 61 | 62 |
| 62 void GetHardwareInfo() { | 63 void GetHardwareInfo() { |
| 63 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 64 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 64 AutoLock lock(lock_); | 65 AutoLock lock(lock_); |
| 66 can_report_metrics_ = true; |
| 67 #if defined(OS_WIN) |
| 65 value_ = UTF16ToUTF8( | 68 value_ = UTF16ToUTF8( |
| 66 installer::WMIComputerSystem::GetModel() + L"|" + | 69 installer::WMIComputerSystem::GetModel() + L"|" + |
| 67 AudioManager::GetAudioManager()->GetAudioInputDeviceModel()); | 70 AudioManager::GetAudioManager()->GetAudioInputDeviceModel()); |
| 71 #else // defined(OS_WIN) |
| 72 value_ = UTF16ToUTF8( |
| 73 AudioManager::GetAudioManager()->GetAudioInputDeviceModel()); |
| 74 #endif // defined(OS_WIN) |
| 68 } | 75 } |
| 69 | 76 |
| 70 std::string value() { | 77 std::string value() { |
| 71 AutoLock lock(lock_); | 78 AutoLock lock(lock_); |
| 72 return value_; | 79 return value_; |
| 73 } | 80 } |
| 74 | 81 |
| 82 bool can_report_metrics() { |
| 83 AutoLock lock(lock_); |
| 84 return can_report_metrics_; |
| 85 } |
| 86 |
| 75 private: | 87 private: |
| 76 Lock lock_; | 88 Lock lock_; |
| 77 std::string value_; | 89 std::string value_; |
| 90 bool can_report_metrics_; |
| 78 | 91 |
| 79 #else // defined(OS_WIN) | 92 DISALLOW_COPY_AND_ASSIGN(OptionalRequestInfo); |
| 80 void Refresh() {} | |
| 81 std::string value() { return std::string(); } | |
| 82 #endif // defined(OS_WIN) | |
| 83 | |
| 84 DISALLOW_COPY_AND_ASSIGN(HardwareInfo); | |
| 85 }; | 93 }; |
| 86 | 94 |
| 87 } // namespace | 95 } // namespace |
| 88 | 96 |
| 89 namespace speech_input { | 97 namespace speech_input { |
| 90 | 98 |
| 91 class SpeechInputManagerImpl : public SpeechInputManager, | 99 class SpeechInputManagerImpl : public SpeechInputManager, |
| 92 public SpeechInputBubbleControllerDelegate, | 100 public SpeechInputBubbleControllerDelegate, |
| 93 public SpeechRecognizerDelegate { | 101 public SpeechRecognizerDelegate { |
| 94 public: | 102 public: |
| 95 // SpeechInputManager methods. | 103 // SpeechInputManager methods. |
| 96 virtual void StartRecognition(SpeechInputManagerDelegate* delegate, | 104 virtual void StartRecognition(SpeechInputManagerDelegate* delegate, |
| 97 int caller_id, | 105 int caller_id, |
| 98 int render_process_id, | 106 int render_process_id, |
| 99 int render_view_id, | 107 int render_view_id, |
| 100 const gfx::Rect& element_rect, | 108 const gfx::Rect& element_rect, |
| 101 const std::string& language, | 109 const std::string& language, |
| 102 const std::string& grammar); | 110 const std::string& grammar, |
| 111 const std::string& origin_url); |
| 103 virtual void CancelRecognition(int caller_id); | 112 virtual void CancelRecognition(int caller_id); |
| 104 virtual void StopRecording(int caller_id); | 113 virtual void StopRecording(int caller_id); |
| 105 | 114 |
| 106 // SpeechRecognizer::Delegate methods. | 115 // SpeechRecognizer::Delegate methods. |
| 107 virtual void SetRecognitionResult(int caller_id, | 116 virtual void SetRecognitionResult(int caller_id, |
| 108 bool error, | 117 bool error, |
| 109 const SpeechInputResultArray& result); | 118 const SpeechInputResultArray& result); |
| 110 virtual void DidCompleteRecording(int caller_id); | 119 virtual void DidCompleteRecording(int caller_id); |
| 111 virtual void DidCompleteRecognition(int caller_id); | 120 virtual void DidCompleteRecognition(int caller_id); |
| 112 virtual void OnRecognizerError(int caller_id, | 121 virtual void OnRecognizerError(int caller_id, |
| (...skipping 23 matching lines...) Expand all Loading... |
| 136 | 145 |
| 137 void CancelRecognitionAndInformDelegate(int caller_id); | 146 void CancelRecognitionAndInformDelegate(int caller_id); |
| 138 | 147 |
| 139 // Starts/restarts recognition for an existing request. | 148 // Starts/restarts recognition for an existing request. |
| 140 void StartRecognitionForRequest(int caller_id); | 149 void StartRecognitionForRequest(int caller_id); |
| 141 | 150 |
| 142 typedef std::map<int, SpeechInputRequest> SpeechRecognizerMap; | 151 typedef std::map<int, SpeechInputRequest> SpeechRecognizerMap; |
| 143 SpeechRecognizerMap requests_; | 152 SpeechRecognizerMap requests_; |
| 144 int recording_caller_id_; | 153 int recording_caller_id_; |
| 145 scoped_refptr<SpeechInputBubbleController> bubble_controller_; | 154 scoped_refptr<SpeechInputBubbleController> bubble_controller_; |
| 146 scoped_refptr<HardwareInfo> hardware_info_; | 155 scoped_refptr<OptionalRequestInfo> optional_request_info_; |
| 147 }; | 156 }; |
| 148 | 157 |
| 149 static ::base::LazyInstance<SpeechInputManagerImpl> g_speech_input_manager_impl( | 158 static ::base::LazyInstance<SpeechInputManagerImpl> g_speech_input_manager_impl( |
| 150 base::LINKER_INITIALIZED); | 159 base::LINKER_INITIALIZED); |
| 151 | 160 |
| 152 SpeechInputManager* SpeechInputManager::Get() { | 161 SpeechInputManager* SpeechInputManager::Get() { |
| 153 return g_speech_input_manager_impl.Pointer(); | 162 return g_speech_input_manager_impl.Pointer(); |
| 154 } | 163 } |
| 155 | 164 |
| 156 bool SpeechInputManager::IsFeatureEnabled() { | 165 bool SpeechInputManager::IsFeatureEnabled() { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 193 return requests_.find(caller_id)->second.delegate; | 202 return requests_.find(caller_id)->second.delegate; |
| 194 } | 203 } |
| 195 | 204 |
| 196 void SpeechInputManagerImpl::StartRecognition( | 205 void SpeechInputManagerImpl::StartRecognition( |
| 197 SpeechInputManagerDelegate* delegate, | 206 SpeechInputManagerDelegate* delegate, |
| 198 int caller_id, | 207 int caller_id, |
| 199 int render_process_id, | 208 int render_process_id, |
| 200 int render_view_id, | 209 int render_view_id, |
| 201 const gfx::Rect& element_rect, | 210 const gfx::Rect& element_rect, |
| 202 const std::string& language, | 211 const std::string& language, |
| 203 const std::string& grammar) { | 212 const std::string& grammar, |
| 213 const std::string& origin_url) { |
| 204 DCHECK(!HasPendingRequest(caller_id)); | 214 DCHECK(!HasPendingRequest(caller_id)); |
| 205 | 215 |
| 206 bubble_controller_->CreateBubble(caller_id, render_process_id, render_view_id, | 216 bubble_controller_->CreateBubble(caller_id, render_process_id, render_view_id, |
| 207 element_rect); | 217 element_rect); |
| 208 | 218 |
| 209 if (!hardware_info_.get()) { | 219 if (!optional_request_info_.get()) { |
| 210 hardware_info_ = new HardwareInfo(); | 220 optional_request_info_ = new OptionalRequestInfo(); |
| 211 // Since hardware info is optional with speech input requests, we start an | 221 // Since hardware info is optional with speech input requests, we start an |
| 212 // asynchronous fetch here and move on with recording audio. This first | 222 // asynchronous fetch here and move on with recording audio. This first |
| 213 // speech input request would send an empty string for hardware info and | 223 // speech input request would send an empty string for hardware info and |
| 214 // subsequent requests may have the hardware info available if the fetch | 224 // subsequent requests may have the hardware info available if the fetch |
| 215 // completed before them. This way we don't end up stalling the user with | 225 // completed before them. This way we don't end up stalling the user with |
| 216 // a long wait and disk seeks when they click on a UI element and start | 226 // a long wait and disk seeks when they click on a UI element and start |
| 217 // speaking. | 227 // speaking. |
| 218 hardware_info_->Refresh(); | 228 optional_request_info_->Refresh(); |
| 219 } | 229 } |
| 220 | 230 |
| 221 SpeechInputRequest* request = &requests_[caller_id]; | 231 SpeechInputRequest* request = &requests_[caller_id]; |
| 222 request->delegate = delegate; | 232 request->delegate = delegate; |
| 223 request->recognizer = new SpeechRecognizer(this, caller_id, language, | 233 request->recognizer = new SpeechRecognizer( |
| 224 grammar, hardware_info_->value()); | 234 this, caller_id, language, grammar, optional_request_info_->value(), |
| 235 optional_request_info_->can_report_metrics() ? origin_url : ""); |
| 225 request->is_active = false; | 236 request->is_active = false; |
| 226 | 237 |
| 227 StartRecognitionForRequest(caller_id); | 238 StartRecognitionForRequest(caller_id); |
| 228 } | 239 } |
| 229 | 240 |
| 230 void SpeechInputManagerImpl::StartRecognitionForRequest(int caller_id) { | 241 void SpeechInputManagerImpl::StartRecognitionForRequest(int caller_id) { |
| 231 DCHECK(HasPendingRequest(caller_id)); | 242 DCHECK(HasPendingRequest(caller_id)); |
| 232 | 243 |
| 233 // If we are currently recording audio for another caller, abort that cleanly. | 244 // If we are currently recording audio for another caller, abort that cleanly. |
| 234 if (recording_caller_id_) | 245 if (recording_caller_id_) |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 354 // to the user, abort it since user has switched focus. Otherwise | 365 // to the user, abort it since user has switched focus. Otherwise |
| 355 // recognition has started and keep that going so user can start speaking to | 366 // recognition has started and keep that going so user can start speaking to |
| 356 // another element while this gets the results in parallel. | 367 // another element while this gets the results in parallel. |
| 357 if (recording_caller_id_ == caller_id || !requests_[caller_id].is_active) { | 368 if (recording_caller_id_ == caller_id || !requests_[caller_id].is_active) { |
| 358 CancelRecognitionAndInformDelegate(caller_id); | 369 CancelRecognitionAndInformDelegate(caller_id); |
| 359 } | 370 } |
| 360 } | 371 } |
| 361 } | 372 } |
| 362 | 373 |
| 363 } // namespace speech_input | 374 } // namespace speech_input |
| OLD | NEW |