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 |