Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(583)

Side by Side Diff: chrome/browser/speech/chrome_speech_input_manager.cc

Issue 7838028: Refactor SpeechInputManager between chrome/ and content/. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: " Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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_input_manager.h" 5 #include "chrome/browser/speech/chrome_speech_input_manager.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/synchronization/lock.h" 9 #include "base/synchronization/lock.h"
10 #include "base/threading/thread_restrictions.h" 10 #include "base/threading/thread_restrictions.h"
11 #include "base/utf_string_conversions.h" 11 #include "base/utf_string_conversions.h"
12 #include "chrome/browser/browser_process.h" 12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/prefs/pref_service.h" 13 #include "chrome/browser/prefs/pref_service.h"
14 #include "chrome/browser/tab_contents/tab_util.h" 14 #include "chrome/browser/tab_contents/tab_util.h"
15 #include "chrome/common/chrome_switches.h"
16 #include "chrome/common/pref_names.h" 15 #include "chrome/common/pref_names.h"
17 #include "content/browser/browser_thread.h" 16 #include "content/browser/browser_thread.h"
18 #include "grit/generated_resources.h" 17 #include "grit/generated_resources.h"
19 #include "media/audio/audio_manager.h" 18 #include "media/audio/audio_manager.h"
20 #include "ui/base/l10n/l10n_util.h" 19 #include "ui/base/l10n/l10n_util.h"
21 20
22 #if defined(OS_WIN) 21 #if defined(OS_WIN)
23 #include "chrome/installer/util/wmi.h" 22 #include "chrome/installer/util/wmi.h"
24 #endif 23 #endif
25 24
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 base::AutoLock lock(lock_); 69 base::AutoLock lock(lock_);
71 return value_; 70 return value_;
72 } 71 }
73 72
74 bool can_report_metrics() { 73 bool can_report_metrics() {
75 base::AutoLock lock(lock_); 74 base::AutoLock lock(lock_);
76 return can_report_metrics_; 75 return can_report_metrics_;
77 } 76 }
78 77
79 private: 78 private:
79 friend class base::RefCountedThreadSafe<OptionalRequestInfo>;
80
81 ~OptionalRequestInfo() {}
82
80 base::Lock lock_; 83 base::Lock lock_;
81 std::string value_; 84 std::string value_;
82 bool can_report_metrics_; 85 bool can_report_metrics_;
83 86
84 DISALLOW_COPY_AND_ASSIGN(OptionalRequestInfo); 87 DISALLOW_COPY_AND_ASSIGN(OptionalRequestInfo);
85 }; 88 };
86 89
87 ChromeSpeechInputManager::SpeechInputRequest::SpeechInputRequest() 90 ChromeSpeechInputManager::SpeechInputRequest::SpeechInputRequest()
88 : delegate(NULL), 91 : delegate(NULL),
89 is_active(false) { 92 is_active(false) {
90 } 93 }
91 94
92 ChromeSpeechInputManager::SpeechInputRequest::~SpeechInputRequest() { 95 ChromeSpeechInputManager::SpeechInputRequest::~SpeechInputRequest() {
93 } 96 }
94 97
95 ChromeSpeechInputManager* ChromeSpeechInputManager::GetInstance() { 98 ChromeSpeechInputManager* ChromeSpeechInputManager::GetInstance() {
96 return Singleton<ChromeSpeechInputManager>::get(); 99 return Singleton<ChromeSpeechInputManager>::get();
97 } 100 }
98 101
99 ChromeSpeechInputManager::ChromeSpeechInputManager() 102 ChromeSpeechInputManager::ChromeSpeechInputManager()
100 : recording_caller_id_(0), 103 : bubble_controller_(new SpeechInputBubbleController(
101 bubble_controller_(new SpeechInputBubbleController(
102 ALLOW_THIS_IN_INITIALIZER_LIST(this))) { 104 ALLOW_THIS_IN_INITIALIZER_LIST(this))) {
103 } 105 }
104 106
105 ChromeSpeechInputManager::~ChromeSpeechInputManager() { 107 ChromeSpeechInputManager::~ChromeSpeechInputManager() {
106 while (requests_.begin() != requests_.end())
107 CancelRecognition(requests_.begin()->first);
108 } 108 }
109 109
110 bool ChromeSpeechInputManager::HasPendingRequest(int caller_id) const { 110 void ChromeSpeechInputManager::ShowRecognitionRequested(
111 return requests_.find(caller_id) != requests_.end();
112 }
113
114 SpeechInputManagerDelegate* ChromeSpeechInputManager::GetDelegate(
115 int caller_id) const {
116 return requests_.find(caller_id)->second.delegate;
117 }
118
119 void ChromeSpeechInputManager::StartRecognition(
120 SpeechInputManagerDelegate* delegate,
121 int caller_id, 111 int caller_id,
122 int render_process_id, 112 int render_process_id,
123 int render_view_id, 113 int render_view_id,
124 const gfx::Rect& element_rect, 114 const gfx::Rect& element_rect) {
125 const std::string& language, 115 bubble_controller_->CreateBubble(caller_id, render_process_id,
126 const std::string& grammar, 116 render_view_id, element_rect);
127 const std::string& origin_url) { 117 }
128 DCHECK(!HasPendingRequest(caller_id));
129 118
130 bubble_controller_->CreateBubble(caller_id, render_process_id, render_view_id, 119 void ChromeSpeechInputManager::GetRequestInfo(
131 element_rect); 120 bool* can_report_metrics, std::string* request_info) {
132
133 if (!optional_request_info_.get()) { 121 if (!optional_request_info_.get()) {
134 optional_request_info_ = new OptionalRequestInfo(); 122 optional_request_info_ = new OptionalRequestInfo();
135 // Since hardware info is optional with speech input requests, we start an 123 // Since hardware info is optional with speech input requests, we start an
136 // asynchronous fetch here and move on with recording audio. This first 124 // asynchronous fetch here and move on with recording audio. This first
137 // speech input request would send an empty string for hardware info and 125 // speech input request would send an empty string for hardware info and
138 // subsequent requests may have the hardware info available if the fetch 126 // subsequent requests may have the hardware info available if the fetch
139 // completed before them. This way we don't end up stalling the user with 127 // completed before them. This way we don't end up stalling the user with
140 // a long wait and disk seeks when they click on a UI element and start 128 // a long wait and disk seeks when they click on a UI element and start
141 // speaking. 129 // speaking.
142 optional_request_info_->Refresh(); 130 optional_request_info_->Refresh();
143 } 131 }
144 132 *can_report_metrics = optional_request_info_->can_report_metrics();
145 SpeechInputRequest* request = &requests_[caller_id]; 133 *request_info = optional_request_info_->value();
146 request->delegate = delegate;
147 request->recognizer = new SpeechRecognizer(
148 this, caller_id, language, grammar, censor_results(),
149 optional_request_info_->value(),
150 optional_request_info_->can_report_metrics() ? origin_url : "");
151 request->is_active = false;
152
153 StartRecognitionForRequest(caller_id);
154 } 134 }
155 135
156 void ChromeSpeechInputManager::StartRecognitionForRequest(int caller_id) { 136 void ChromeSpeechInputManager::ShowWarmUp(int caller_id) {
157 DCHECK(HasPendingRequest(caller_id)); 137 bubble_controller_->SetBubbleWarmUpMode(caller_id);
158
159 // If we are currently recording audio for another caller, abort that cleanly.
160 if (recording_caller_id_)
161 CancelRecognitionAndInformDelegate(recording_caller_id_);
162
163 if (!AudioManager::GetAudioManager()->HasAudioInputDevices()) {
164 bubble_controller_->SetBubbleMessage(
165 caller_id, l10n_util::GetStringUTF16(IDS_SPEECH_INPUT_NO_MIC));
166 } else {
167 recording_caller_id_ = caller_id;
168 requests_[caller_id].is_active = true;
169 requests_[caller_id].recognizer->StartRecording();
170 bubble_controller_->SetBubbleWarmUpMode(caller_id);
171 }
172 } 138 }
173 139
174 void ChromeSpeechInputManager::CancelRecognition(int caller_id) { 140 void ChromeSpeechInputManager::ShowRecognizing(int caller_id) {
175 DCHECK(HasPendingRequest(caller_id));
176 if (requests_[caller_id].is_active)
177 requests_[caller_id].recognizer->CancelRecognition();
178 requests_.erase(caller_id);
179 if (recording_caller_id_ == caller_id)
180 recording_caller_id_ = 0;
181 bubble_controller_->CloseBubble(caller_id);
182 }
183
184 void ChromeSpeechInputManager::CancelAllRequestsWithDelegate(
185 SpeechInputManagerDelegate* delegate) {
186 SpeechRecognizerMap::iterator it = requests_.begin();
187 while (it != requests_.end()) {
188 if (it->second.delegate == delegate) {
189 CancelRecognition(it->first);
190 // This map will have very few elements so it is simpler to restart.
191 it = requests_.begin();
192 } else {
193 ++it;
194 }
195 }
196 }
197
198 void ChromeSpeechInputManager::StopRecording(int caller_id) {
199 DCHECK(HasPendingRequest(caller_id));
200 requests_[caller_id].recognizer->StopRecording();
201 }
202
203 void ChromeSpeechInputManager::SetRecognitionResult(
204 int caller_id, bool error, const SpeechInputResultArray& result) {
205 DCHECK(HasPendingRequest(caller_id));
206 GetDelegate(caller_id)->SetRecognitionResult(caller_id, result);
207 }
208
209 void ChromeSpeechInputManager::DidCompleteRecording(int caller_id) {
210 DCHECK(recording_caller_id_ == caller_id);
211 DCHECK(HasPendingRequest(caller_id));
212 recording_caller_id_ = 0;
213 GetDelegate(caller_id)->DidCompleteRecording(caller_id);
214 bubble_controller_->SetBubbleRecognizingMode(caller_id); 141 bubble_controller_->SetBubbleRecognizingMode(caller_id);
215 } 142 }
216 143
217 void ChromeSpeechInputManager::DidCompleteRecognition(int caller_id) { 144 void ChromeSpeechInputManager::ShowRecording(int caller_id) {
218 GetDelegate(caller_id)->DidCompleteRecognition(caller_id); 145 bubble_controller_->SetBubbleRecordingMode(caller_id);
219 requests_.erase(caller_id);
220 bubble_controller_->CloseBubble(caller_id);
221 } 146 }
222 147
223 void ChromeSpeechInputManager::OnRecognizerError( 148 void ChromeSpeechInputManager::ShowInputVolume(
149 int caller_id, float volume, float noise_volume) {
150 bubble_controller_->SetBubbleInputVolume(caller_id, volume, noise_volume);
151 }
152
153 void ChromeSpeechInputManager::ShowNoMicError(int caller_id) {
154 bubble_controller_->SetBubbleMessage(
155 caller_id, l10n_util::GetStringUTF16(IDS_SPEECH_INPUT_NO_MIC));
156 }
157
158 void ChromeSpeechInputManager::ShowRecognizerError(
224 int caller_id, SpeechRecognizer::ErrorCode error) { 159 int caller_id, SpeechRecognizer::ErrorCode error) {
225 if (caller_id == recording_caller_id_)
226 recording_caller_id_ = 0;
227
228 requests_[caller_id].is_active = false;
229
230 struct ErrorMessageMapEntry { 160 struct ErrorMessageMapEntry {
231 SpeechRecognizer::ErrorCode error; 161 SpeechRecognizer::ErrorCode error;
232 int message_id; 162 int message_id;
233 }; 163 };
234 ErrorMessageMapEntry error_message_map[] = { 164 ErrorMessageMapEntry error_message_map[] = {
235 { 165 {
236 SpeechRecognizer::RECOGNIZER_ERROR_CAPTURE, IDS_SPEECH_INPUT_MIC_ERROR 166 SpeechRecognizer::RECOGNIZER_ERROR_CAPTURE, IDS_SPEECH_INPUT_MIC_ERROR
237 }, { 167 }, {
238 SpeechRecognizer::RECOGNIZER_ERROR_NO_SPEECH, IDS_SPEECH_INPUT_NO_SPEECH 168 SpeechRecognizer::RECOGNIZER_ERROR_NO_SPEECH, IDS_SPEECH_INPUT_NO_SPEECH
239 }, { 169 }, {
240 SpeechRecognizer::RECOGNIZER_ERROR_NO_RESULTS, IDS_SPEECH_INPUT_NO_RESULTS 170 SpeechRecognizer::RECOGNIZER_ERROR_NO_RESULTS, IDS_SPEECH_INPUT_NO_RESULTS
241 }, { 171 }, {
242 SpeechRecognizer::RECOGNIZER_ERROR_NETWORK, IDS_SPEECH_INPUT_NET_ERROR 172 SpeechRecognizer::RECOGNIZER_ERROR_NETWORK, IDS_SPEECH_INPUT_NET_ERROR
243 } 173 }
244 }; 174 };
245 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(error_message_map); ++i) { 175 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(error_message_map); ++i) {
246 if (error_message_map[i].error == error) { 176 if (error_message_map[i].error == error) {
247 bubble_controller_->SetBubbleMessage( 177 bubble_controller_->SetBubbleMessage(
248 caller_id, 178 caller_id,
249 l10n_util::GetStringUTF16(error_message_map[i].message_id)); 179 l10n_util::GetStringUTF16(error_message_map[i].message_id));
250 return; 180 return;
251 } 181 }
252 } 182 }
253 183
254 NOTREACHED() << "unknown error " << error; 184 NOTREACHED() << "unknown error " << error;
255 } 185 }
256 186
257 void ChromeSpeechInputManager::DidStartReceivingAudio(int caller_id) { 187 void ChromeSpeechInputManager::DoClose(int caller_id) {
258 DCHECK(HasPendingRequest(caller_id)); 188 bubble_controller_->CloseBubble(caller_id);
259 DCHECK(recording_caller_id_ == caller_id);
260 bubble_controller_->SetBubbleRecordingMode(caller_id);
261 }
262
263 void ChromeSpeechInputManager::DidCompleteEnvironmentEstimation(int caller_id) {
264 DCHECK(HasPendingRequest(caller_id));
265 DCHECK(recording_caller_id_ == caller_id);
266 }
267
268 void ChromeSpeechInputManager::SetInputVolume(int caller_id, float volume,
269 float noise_volume) {
270 DCHECK(HasPendingRequest(caller_id));
271 DCHECK_EQ(recording_caller_id_, caller_id);
272
273 bubble_controller_->SetBubbleInputVolume(caller_id, volume, noise_volume);
274 }
275
276 void ChromeSpeechInputManager::CancelRecognitionAndInformDelegate(
277 int caller_id) {
278 SpeechInputManagerDelegate* cur_delegate = GetDelegate(caller_id);
279 CancelRecognition(caller_id);
280 cur_delegate->DidCompleteRecording(caller_id);
281 cur_delegate->DidCompleteRecognition(caller_id);
282 } 189 }
283 190
284 void ChromeSpeechInputManager::InfoBubbleButtonClicked( 191 void ChromeSpeechInputManager::InfoBubbleButtonClicked(
285 int caller_id, SpeechInputBubble::Button button) { 192 int caller_id, SpeechInputBubble::Button button) {
286 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 193 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
287 // Ignore if the caller id was not in our active recognizers list because the 194 // Ignore if the caller id was not in our active recognizers list because the
288 // user might have clicked more than once, or recognition could have been 195 // user might have clicked more than once, or recognition could have been
289 // cancelled due to other reasons before the user click was processed. 196 // cancelled due to other reasons before the user click was processed.
290 if (!HasPendingRequest(caller_id)) 197 if (!HasPendingRequest(caller_id))
291 return; 198 return;
292 199
293 if (button == SpeechInputBubble::BUTTON_CANCEL) { 200 if (button == SpeechInputBubble::BUTTON_CANCEL) {
294 CancelRecognitionAndInformDelegate(caller_id); 201 CancelRecognitionAndInformDelegate(caller_id);
295 } else if (button == SpeechInputBubble::BUTTON_TRY_AGAIN) { 202 } else if (button == SpeechInputBubble::BUTTON_TRY_AGAIN) {
296 StartRecognitionForRequest(caller_id); 203 StartRecognitionForRequest(caller_id);
297 } 204 }
298 } 205 }
299 206
300 void ChromeSpeechInputManager::InfoBubbleFocusChanged(int caller_id) { 207 void ChromeSpeechInputManager::InfoBubbleFocusChanged(int caller_id) {
301 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 208 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
302 // Ignore if the caller id was not in our active recognizers list because the 209 OnFocusChanged(caller_id);
303 // user might have clicked more than once, or recognition could have been
304 // ended due to other reasons before the user click was processed.
305 if (HasPendingRequest(caller_id)) {
306 // If this is an ongoing recording or if we were displaying an error message
307 // to the user, abort it since user has switched focus. Otherwise
308 // recognition has started and keep that going so user can start speaking to
309 // another element while this gets the results in parallel.
310 if (recording_caller_id_ == caller_id || !requests_[caller_id].is_active) {
311 CancelRecognitionAndInformDelegate(caller_id);
312 }
313 }
314 } 210 }
315 211
316 } // namespace speech_input 212 } // namespace speech_input
OLDNEW
« no previous file with comments | « chrome/browser/speech/chrome_speech_input_manager.h ('k') | content/browser/speech/speech_input_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698