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

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

Issue 10377082: SpeechInputExtensionManager now interface with SpeechRecognitionManagerDelegate (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebased Created 8 years, 7 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) 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/speech_input_extension_manager.h" 5 #include "chrome/browser/speech/speech_input_extension_manager.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/json/json_writer.h" 8 #include "base/json/json_writer.h"
9 #include "base/utf_string_conversions.h" 9 #include "base/utf_string_conversions.h"
10 #include "base/values.h" 10 #include "base/values.h"
11 #include "chrome/browser/extensions/extension_event_router.h" 11 #include "chrome/browser/extensions/extension_event_router.h"
12 #include "chrome/browser/extensions/extension_service.h" 12 #include "chrome/browser/extensions/extension_service.h"
13 #include "chrome/browser/prefs/pref_service.h" 13 #include "chrome/browser/prefs/pref_service.h"
14 #include "chrome/browser/profiles/profile.h" 14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/profiles/profile_dependency_manager.h" 15 #include "chrome/browser/profiles/profile_dependency_manager.h"
16 #include "chrome/browser/profiles/profile_keyed_service.h" 16 #include "chrome/browser/profiles/profile_keyed_service.h"
17 #include "chrome/browser/profiles/profile_keyed_service_factory.h" 17 #include "chrome/browser/profiles/profile_keyed_service_factory.h"
18 #include "chrome/browser/speech/speech_recognition_tray_icon_controller.h"
19 #include "chrome/common/chrome_notification_types.h" 18 #include "chrome/common/chrome_notification_types.h"
20 #include "chrome/common/extensions/extension.h" 19 #include "chrome/common/extensions/extension.h"
21 #include "chrome/common/pref_names.h" 20 #include "chrome/common/pref_names.h"
22 #include "content/public/browser/browser_thread.h" 21 #include "content/public/browser/browser_thread.h"
23 #include "content/public/browser/notification_registrar.h" 22 #include "content/public/browser/notification_registrar.h"
24 #include "content/public/browser/notification_service.h" 23 #include "content/public/browser/notification_service.h"
25 #include "content/public/browser/speech_recognition_manager.h" 24 #include "content/public/browser/speech_recognition_manager.h"
26 #include "content/public/browser/speech_recognizer.h" 25 #include "content/public/browser/speech_recognition_session_config.h"
26 #include "content/public/browser/speech_recognition_session_context.h"
27 #include "content/public/common/speech_recognition_error.h" 27 #include "content/public/common/speech_recognition_error.h"
28 #include "content/public/common/speech_recognition_result.h" 28 #include "content/public/common/speech_recognition_result.h"
29 #include "net/url_request/url_request_context_getter.h"
29 30
30 using content::BrowserThread; 31 using content::BrowserThread;
31 using content::SpeechRecognitionHypothesis; 32 using content::SpeechRecognitionHypothesis;
32 using content::SpeechRecognitionManager; 33 using content::SpeechRecognitionManager;
33 34
34 namespace { 35 namespace {
35 36
36 const char kErrorNoRecordingDeviceFound[] = "noRecordingDeviceFound"; 37 const char kErrorNoRecordingDeviceFound[] = "noRecordingDeviceFound";
37 const char kErrorRecordingDeviceInUse[] = "recordingDeviceInUse"; 38 const char kErrorRecordingDeviceInUse[] = "recordingDeviceInUse";
38 const char kErrorUnableToStart[] = "unableToStart"; 39 const char kErrorUnableToStart[] = "unableToStart";
39 const char kErrorRequestDenied[] = "requestDenied"; 40 const char kErrorRequestDenied[] = "requestDenied";
40 const char kErrorRequestInProgress[] = "requestInProgress"; 41 const char kErrorRequestInProgress[] = "requestInProgress";
41 const char kErrorInvalidOperation[] = "invalidOperation"; 42 const char kErrorInvalidOperation[] = "invalidOperation";
42 43
43 const char kErrorCodeKey[] = "code"; 44 const char kErrorCodeKey[] = "code";
44 const char kErrorCaptureError[] = "captureError"; 45 const char kErrorCaptureError[] = "captureError";
45 const char kErrorNetworkError[] = "networkError"; 46 const char kErrorNetworkError[] = "networkError";
46 const char kErrorNoSpeechHeard[] = "noSpeechHeard"; 47 const char kErrorNoSpeechHeard[] = "noSpeechHeard";
47 const char kErrorNoResults[] = "noResults"; 48 const char kErrorNoResults[] = "noResults";
48 49
49 const char kUtteranceKey[] = "utterance"; 50 const char kUtteranceKey[] = "utterance";
50 const char kConfidenceKey[] = "confidence"; 51 const char kConfidenceKey[] = "confidence";
51 const char kHypothesesKey[] = "hypotheses"; 52 const char kHypothesesKey[] = "hypotheses";
52 53
53 const char kOnErrorEvent[] = "experimental.speechInput.onError"; 54 const char kOnErrorEvent[] = "experimental.speechInput.onError";
54 const char kOnResultEvent[] = "experimental.speechInput.onResult"; 55 const char kOnResultEvent[] = "experimental.speechInput.onResult";
55 const char kOnSoundStartEvent[] = "experimental.speechInput.onSoundStart"; 56 const char kOnSoundStartEvent[] = "experimental.speechInput.onSoundStart";
56 const char kOnSoundEndEvent[] = "experimental.speechInput.onSoundEnd"; 57 const char kOnSoundEndEvent[] = "experimental.speechInput.onSoundEnd";
57 58
58 // Session id provided to the speech recognizer. Since only one extension can
59 // be recording on the same time a constant value is enough as id.
60 // TODO(primiano) this will not be valid anymore once speech input extension
61 // will use the SpeechRecognitionManager and not the SpeechRecognizer directly.
62 static const int kSpeechInputSessionId = 1;
63
64 // Wrap an SpeechInputExtensionManager using scoped_refptr to avoid 59 // Wrap an SpeechInputExtensionManager using scoped_refptr to avoid
65 // assertion failures on destruction because of not using release(). 60 // assertion failures on destruction because of not using release().
66 class SpeechInputExtensionManagerWrapper : public ProfileKeyedService { 61 class SpeechInputExtensionManagerWrapper : public ProfileKeyedService {
67 public: 62 public:
68 explicit SpeechInputExtensionManagerWrapper( 63 explicit SpeechInputExtensionManagerWrapper(
69 SpeechInputExtensionManager* manager) 64 SpeechInputExtensionManager* manager)
70 : manager_(manager) {} 65 : manager_(manager) {}
71 66
72 virtual ~SpeechInputExtensionManagerWrapper() {} 67 virtual ~SpeechInputExtensionManagerWrapper() {}
73 68
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 SpeechInputExtensionInterface::SpeechInputExtensionInterface() { 145 SpeechInputExtensionInterface::SpeechInputExtensionInterface() {
151 } 146 }
152 147
153 SpeechInputExtensionInterface::~SpeechInputExtensionInterface() { 148 SpeechInputExtensionInterface::~SpeechInputExtensionInterface() {
154 } 149 }
155 150
156 SpeechInputExtensionManager::SpeechInputExtensionManager(Profile* profile) 151 SpeechInputExtensionManager::SpeechInputExtensionManager(Profile* profile)
157 : profile_(profile), 152 : profile_(profile),
158 state_(kIdle), 153 state_(kIdle),
159 registrar_(new content::NotificationRegistrar), 154 registrar_(new content::NotificationRegistrar),
160 speech_interface_(NULL) { 155 speech_interface_(NULL),
156 is_recognition_in_progress_(false),
157 speech_recognition_session_id_(
158 SpeechRecognitionManager::kSessionIDInvalid) {
161 registrar_->Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, 159 registrar_->Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
162 content::Source<Profile>(profile_)); 160 content::Source<Profile>(profile_));
163 } 161 }
164 162
165 SpeechInputExtensionManager::~SpeechInputExtensionManager() { 163 SpeechInputExtensionManager::~SpeechInputExtensionManager() {
166 } 164 }
167 165
168 SpeechInputExtensionManager* SpeechInputExtensionManager::GetForProfile( 166 SpeechInputExtensionManager* SpeechInputExtensionManager::GetForProfile(
169 Profile* profile) { 167 Profile* profile) {
170 SpeechInputExtensionManagerWrapper* wrapper = 168 SpeechInputExtensionManagerWrapper* wrapper =
(...skipping 15 matching lines...) Expand all
186 content::Details<UnloadedExtensionInfo>(details)->extension->id()); 184 content::Details<UnloadedExtensionInfo>(details)->extension->id());
187 } else { 185 } else {
188 NOTREACHED(); 186 NOTREACHED();
189 } 187 }
190 } 188 }
191 189
192 void SpeechInputExtensionManager::ShutdownOnUIThread() { 190 void SpeechInputExtensionManager::ShutdownOnUIThread() {
193 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 191 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
194 VLOG(1) << "Profile shutting down."; 192 VLOG(1) << "Profile shutting down.";
195 193
194 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
195 base::Bind(&SpeechRecognitionManager::AbortAllSessionsForListener,
196 base::Unretained(SpeechRecognitionManager::GetInstance()),
197 base::Unretained(this)));
198
196 base::AutoLock auto_lock(state_lock_); 199 base::AutoLock auto_lock(state_lock_);
197 DCHECK(state_ != kShutdown); 200 DCHECK(state_ != kShutdown);
198 if (state_ != kIdle) { 201 if (state_ != kIdle) {
199 DCHECK(notification_.get());
200 notification_->Hide();
201 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 202 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
202 base::Bind(&SpeechInputExtensionManager::ForceStopOnIOThread, this)); 203 base::Bind(&SpeechInputExtensionManager::ForceStopOnIOThread, this));
203 } 204 }
204 state_ = kShutdown; 205 state_ = kShutdown;
205 VLOG(1) << "Entering the shutdown sink state."; 206 VLOG(1) << "Entering the shutdown sink state.";
206 registrar_.reset(); 207 registrar_.reset();
207 profile_ = NULL; 208 profile_ = NULL;
208 } 209 }
209 210
210 void SpeechInputExtensionManager::ExtensionUnloaded( 211 void SpeechInputExtensionManager::ExtensionUnloaded(
(...skipping 26 matching lines...) Expand all
237 void SpeechInputExtensionManager::ResetToIdleState() { 238 void SpeechInputExtensionManager::ResetToIdleState() {
238 VLOG(1) << "State changed to idle. Deassociating any extensions."; 239 VLOG(1) << "State changed to idle. Deassociating any extensions.";
239 state_ = kIdle; 240 state_ = kIdle;
240 extension_id_in_use_.clear(); 241 extension_id_in_use_.clear();
241 } 242 }
242 243
243 void SpeechInputExtensionManager::OnRecognitionResult( 244 void SpeechInputExtensionManager::OnRecognitionResult(
244 int session_id, 245 int session_id,
245 const content::SpeechRecognitionResult& result) { 246 const content::SpeechRecognitionResult& result) {
246 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 247 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
247 DCHECK_EQ(session_id, kSpeechInputSessionId); 248 DCHECK_EQ(session_id, speech_recognition_session_id_);
248 249
249 // Stopping will start the disassociation with the extension. 250 // Stopping will start the disassociation with the extension.
250 // Make a copy to report the results to the proper one. 251 // Make a copy to report the results to the proper one.
251 std::string extension_id = extension_id_in_use_; 252 std::string extension_id = extension_id_in_use_;
252 ForceStopOnIOThread(); 253 ForceStopOnIOThread();
253 254
254 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 255 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
255 base::Bind(&SpeechInputExtensionManager::SetRecognitionResultOnUIThread, 256 base::Bind(&SpeechInputExtensionManager::SetRecognitionResultOnUIThread,
256 this, result, extension_id)); 257 this, result, extension_id));
257 } 258 }
(...skipping 22 matching lines...) Expand all
280 hypothesis.confidence); 281 hypothesis.confidence);
281 } 282 }
282 283
283 std::string json_args; 284 std::string json_args;
284 base::JSONWriter::Write(&args, &json_args); 285 base::JSONWriter::Write(&args, &json_args);
285 VLOG(1) << "Results: " << json_args; 286 VLOG(1) << "Results: " << json_args;
286 DispatchEventToExtension(extension_id, kOnResultEvent, json_args); 287 DispatchEventToExtension(extension_id, kOnResultEvent, json_args);
287 } 288 }
288 289
289 void SpeechInputExtensionManager::OnRecognitionStart(int session_id) { 290 void SpeechInputExtensionManager::OnRecognitionStart(int session_id) {
290 DCHECK_EQ(session_id, kSpeechInputSessionId); 291 DCHECK_EQ(session_id, speech_recognition_session_id_);
291 } 292 }
292 293
293 void SpeechInputExtensionManager::OnAudioStart(int session_id) { 294 void SpeechInputExtensionManager::OnAudioStart(int session_id) {
294 VLOG(1) << "OnAudioStart"; 295 VLOG(1) << "OnAudioStart";
295 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 296 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
296 DCHECK_EQ(session_id, kSpeechInputSessionId); 297 DCHECK_EQ(session_id, speech_recognition_session_id_);
297 298
298 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 299 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
299 base::Bind(&SpeechInputExtensionManager::DidStartReceivingAudioOnUIThread, 300 base::Bind(&SpeechInputExtensionManager::DidStartReceivingAudioOnUIThread,
300 this)); 301 this));
301 } 302 }
302 303
303 void SpeechInputExtensionManager::OnAudioEnd(int session_id) { 304 void SpeechInputExtensionManager::OnAudioEnd(int session_id) {
304 DCHECK_EQ(session_id, kSpeechInputSessionId);
305 } 305 }
306 306
307 void SpeechInputExtensionManager::OnRecognitionEnd(int session_id) { 307 void SpeechInputExtensionManager::OnRecognitionEnd(int session_id) {
308 DCHECK_EQ(session_id, kSpeechInputSessionId); 308 // In the very exceptional case in which we requested a new recognition before
309 // the previous one ended, don't clobber the speech_recognition_session_id_.
310 if (speech_recognition_session_id_ == session_id) {
311 is_recognition_in_progress_ = false;
312 speech_recognition_session_id_ =
313 SpeechRecognitionManager::kSessionIDInvalid;
314 }
309 } 315 }
310 316
311 void SpeechInputExtensionManager::DidStartReceivingAudioOnUIThread() { 317 void SpeechInputExtensionManager::DidStartReceivingAudioOnUIThread() {
312 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 318 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
313 319
314 base::AutoLock auto_lock(state_lock_); 320 base::AutoLock auto_lock(state_lock_);
315 if (state_ == kShutdown) 321 if (state_ == kShutdown)
316 return; 322 return;
317 323
318 DCHECK_EQ(state_, kStarting); 324 DCHECK_EQ(state_, kStarting);
319 VLOG(1) << "State changed to recording"; 325 VLOG(1) << "State changed to recording";
320 state_ = kRecording; 326 state_ = kRecording;
321 327
322 const Extension* extension = profile_->GetExtensionService()-> 328 DCHECK(profile_);
323 GetExtensionById(extension_id_in_use_, true); 329 profile_->GetPrefs()->SetBoolean(
324 DCHECK(extension); 330 prefs::kSpeechInputTrayNotificationShown, true);
hans 2012/05/15 13:35:17 this looks like a simplification of the old code..
Primiano Tucci (use gerrit) 2012/05/16 10:16:00 The previous code was doing 3 things: (a) checkin
325
326 bool show_notification = !profile_->GetPrefs()->GetBoolean(
327 prefs::kSpeechInputTrayNotificationShown);
328
329 if (!notification_.get())
330 notification_ = new SpeechRecognitionTrayIconController();
331 notification_->Show(UTF8ToUTF16(extension->name()), show_notification);
332
333 if (show_notification) {
334 profile_->GetPrefs()->SetBoolean(
335 prefs::kSpeechInputTrayNotificationShown, true);
336 }
337 331
338 VLOG(1) << "Sending start notification"; 332 VLOG(1) << "Sending start notification";
339 content::NotificationService::current()->Notify( 333 content::NotificationService::current()->Notify(
340 chrome::NOTIFICATION_EXTENSION_SPEECH_INPUT_RECORDING_STARTED, 334 chrome::NOTIFICATION_EXTENSION_SPEECH_INPUT_RECORDING_STARTED,
341 content::Source<Profile>(profile_), 335 content::Source<Profile>(profile_),
342 content::Details<std::string>(&extension_id_in_use_)); 336 content::Details<std::string>(&extension_id_in_use_));
343 } 337 }
344 338
345 void SpeechInputExtensionManager::OnRecognitionError( 339 void SpeechInputExtensionManager::OnRecognitionError(
346 int session_id, const content::SpeechRecognitionError& error) { 340 int session_id, const content::SpeechRecognitionError& error) {
347 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 341 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
348 DCHECK_EQ(session_id, kSpeechInputSessionId);
349 342
350 // Simply return in case of an ERROR_ABORTED, since it is not contemplated 343 // Simply return in case of an ERROR_ABORTED, since it is not contemplated
351 // in the speech input extensions architecture. 344 // in the speech input extensions architecture.
352 if (error.code == content::SPEECH_RECOGNITION_ERROR_ABORTED) 345 if (error.code == content::SPEECH_RECOGNITION_ERROR_ABORTED)
353 return; 346 return;
354 347
348 DCHECK_EQ(session_id, speech_recognition_session_id_);
355 VLOG(1) << "OnRecognitionError: " << error.code; 349 VLOG(1) << "OnRecognitionError: " << error.code;
356 350
357 base::AutoLock auto_lock(state_lock_); 351 base::AutoLock auto_lock(state_lock_);
358 if (state_ == kShutdown) 352 if (state_ == kShutdown)
359 return; 353 return;
360 354
361 // Release the recognizer object. 355 // Release the recognizer object.
362 GetSpeechInputExtensionInterface()->StopRecording(true); 356 GetSpeechInputExtensionInterface()->StopRecording(true);
363 357
364 std::string event_error_code; 358 std::string event_error_code;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 397
404 if (!event_error_code.empty()) { 398 if (!event_error_code.empty()) {
405 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 399 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
406 base::Bind(&SpeechInputExtensionManager::DispatchError, 400 base::Bind(&SpeechInputExtensionManager::DispatchError,
407 this, event_error_code, report_to_event)); 401 this, event_error_code, report_to_event));
408 } 402 }
409 } 403 }
410 404
411 void SpeechInputExtensionManager::OnEnvironmentEstimationComplete( 405 void SpeechInputExtensionManager::OnEnvironmentEstimationComplete(
412 int session_id) { 406 int session_id) {
413 DCHECK_EQ(session_id, kSpeechInputSessionId); 407 DCHECK_EQ(session_id, speech_recognition_session_id_);
414 } 408 }
415 409
416 void SpeechInputExtensionManager::OnSoundStart(int session_id) { 410 void SpeechInputExtensionManager::OnSoundStart(int session_id) {
417 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 411 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
418 DCHECK_EQ(session_id, kSpeechInputSessionId); 412 DCHECK_EQ(session_id, speech_recognition_session_id_);
419 VLOG(1) << "OnSoundStart"; 413 VLOG(1) << "OnSoundStart";
420 414
421 std::string json_args; 415 std::string json_args;
422 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 416 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
423 base::Bind(&SpeechInputExtensionManager::DispatchEventToExtension, 417 base::Bind(&SpeechInputExtensionManager::DispatchEventToExtension,
424 this, extension_id_in_use_, std::string(kOnSoundStartEvent), 418 this, extension_id_in_use_, std::string(kOnSoundStartEvent),
425 json_args)); 419 json_args));
426 } 420 }
427 421
428 void SpeechInputExtensionManager::OnSoundEnd(int session_id) { 422 void SpeechInputExtensionManager::OnSoundEnd(int session_id) {
429 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 423 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
430 DCHECK_EQ(session_id, kSpeechInputSessionId);
431 VLOG(1) << "OnSoundEnd"; 424 VLOG(1) << "OnSoundEnd";
432 425
433 std::string json_args; 426 std::string json_args;
434 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 427 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
435 base::Bind(&SpeechInputExtensionManager::DispatchEventToExtension, 428 base::Bind(&SpeechInputExtensionManager::DispatchEventToExtension,
436 this, extension_id_in_use_, std::string(kOnSoundEndEvent), 429 this, extension_id_in_use_, std::string(kOnSoundEndEvent),
437 json_args)); 430 json_args));
438 } 431 }
439 432
440 void SpeechInputExtensionManager::DispatchEventToExtension( 433 void SpeechInputExtensionManager::DispatchEventToExtension(
(...skipping 22 matching lines...) Expand all
463 void SpeechInputExtensionManager::DispatchError( 456 void SpeechInputExtensionManager::DispatchError(
464 const std::string& error, bool dispatch_event) { 457 const std::string& error, bool dispatch_event) {
465 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 458 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
466 459
467 std::string extension_id; 460 std::string extension_id;
468 { 461 {
469 base::AutoLock auto_lock(state_lock_); 462 base::AutoLock auto_lock(state_lock_);
470 if (state_ == kShutdown) 463 if (state_ == kShutdown)
471 return; 464 return;
472 465
473 if (state_ == kRecording) {
474 DCHECK(notification_.get());
475 notification_->Hide();
476 }
477
478 extension_id = extension_id_in_use_; 466 extension_id = extension_id_in_use_;
479 ResetToIdleState(); 467 ResetToIdleState();
480 468
481 // Will set the error property in the ongoing extension function calls. 469 // Will set the error property in the ongoing extension function calls.
482 ExtensionError details(extension_id, error); 470 ExtensionError details(extension_id, error);
483 content::NotificationService::current()->Notify( 471 content::NotificationService::current()->Notify(
484 chrome::NOTIFICATION_EXTENSION_SPEECH_INPUT_FAILED, 472 chrome::NOTIFICATION_EXTENSION_SPEECH_INPUT_FAILED,
485 content::Source<Profile>(profile_), 473 content::Source<Profile>(profile_),
486 content::Details<ExtensionError>(&details)); 474 content::Details<ExtensionError>(&details));
487 } 475 }
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
523 511
524 case kRecording: 512 case kRecording:
525 case kStopping: 513 case kStopping:
526 *error = kErrorInvalidOperation; 514 *error = kErrorInvalidOperation;
527 return false; 515 return false;
528 516
529 default: 517 default:
530 NOTREACHED(); 518 NOTREACHED();
531 } 519 }
532 520
521 const Extension* extension = profile_->GetExtensionService()->
522 GetExtensionById(extension_id, true);
523 DCHECK(extension);
524 const string16& extension_name = UTF8ToUTF16(extension->name());
525
533 extension_id_in_use_ = extension_id; 526 extension_id_in_use_ = extension_id;
534 VLOG(1) << "State changed to starting"; 527 VLOG(1) << "State changed to starting";
535 state_ = kStarting; 528 state_ = kStarting;
536 529
530 // Checks if the security notification balloon has been already shown (only
531 // once for a profile). It is reset on DidStartReceivingAudioOnUIThread.
532 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter =
533 profile_->GetRequestContext();
534 const bool show_notification = !profile_->GetPrefs()->GetBoolean(
535 prefs::kSpeechInputTrayNotificationShown);
536
537 BrowserThread::PostTask( 537 BrowserThread::PostTask(
538 BrowserThread::IO, FROM_HERE, 538 BrowserThread::IO, FROM_HERE,
539 base::Bind(&SpeechInputExtensionManager::StartOnIOThread, this, 539 base::Bind(&SpeechInputExtensionManager::StartOnIOThread, this,
540 profile_->GetRequestContext(), language, grammar, 540 url_request_context_getter, extension_name, language, grammar,
541 filter_profanities)); 541 filter_profanities, show_notification));
542 return true; 542 return true;
543 } 543 }
544 544
545 void SpeechInputExtensionManager::StartOnIOThread( 545 void SpeechInputExtensionManager::StartOnIOThread(
546 net::URLRequestContextGetter* context_getter, 546 scoped_refptr<net::URLRequestContextGetter> context_getter,
547 const string16& extension_name,
547 const std::string& language, 548 const std::string& language,
548 const std::string& grammar, 549 const std::string& grammar,
549 bool filter_profanities) { 550 bool filter_profanities,
551 bool show_notification) {
550 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 552 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
551 VLOG(1) << "Requesting start (IO thread)"; 553 VLOG(1) << "Requesting start (IO thread)";
552 554
553 // Everything put inside the lock to ensure the validity of context_getter, 555 // Everything put inside the lock to ensure the validity of context_getter,
554 // guaranteed while not in the shutdown state. Any ongoing or recognition 556 // guaranteed while not in the shutdown state. Any ongoing or recognition
555 // request will be requested to be aborted when entering the shutdown state. 557 // request will be requested to be aborted when entering the shutdown state.
556 base::AutoLock auto_lock(state_lock_); 558 base::AutoLock auto_lock(state_lock_);
557 if (state_ == kShutdown) 559 if (state_ == kShutdown)
558 return; 560 return;
559 561
560 if (!GetSpeechInputExtensionInterface()->HasAudioInputDevices()) { 562 if (!GetSpeechInputExtensionInterface()->HasAudioInputDevices()) {
561 BrowserThread::PostTask( 563 BrowserThread::PostTask(
562 BrowserThread::UI, FROM_HERE, 564 BrowserThread::UI, FROM_HERE,
563 base::Bind(&SpeechInputExtensionManager::DispatchError, this, 565 base::Bind(&SpeechInputExtensionManager::DispatchError, this,
564 std::string(kErrorNoRecordingDeviceFound), false)); 566 std::string(kErrorNoRecordingDeviceFound), false));
565 return; 567 return;
566 } 568 }
567 569
568 if (GetSpeechInputExtensionInterface()->IsCapturingAudio()) { 570 if (GetSpeechInputExtensionInterface()->IsCapturingAudio()) {
569 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 571 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
570 base::Bind(&SpeechInputExtensionManager::DispatchError, this, 572 base::Bind(&SpeechInputExtensionManager::DispatchError, this,
571 std::string(kErrorRecordingDeviceInUse), false)); 573 std::string(kErrorRecordingDeviceInUse), false));
572 return; 574 return;
573 } 575 }
574 576
575 GetSpeechInputExtensionInterface()->StartRecording( 577 GetSpeechInputExtensionInterface()->StartRecording(this,
576 this, context_getter, kSpeechInputSessionId, language, grammar, 578 context_getter,
577 filter_profanities); 579 extension_name,
580 language,
581 grammar,
582 filter_profanities,
583 show_notification);
578 } 584 }
579 585
580 bool SpeechInputExtensionManager::HasAudioInputDevices() { 586 bool SpeechInputExtensionManager::HasAudioInputDevices() {
581 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 587 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
582 return SpeechRecognitionManager::GetInstance()->HasAudioInputDevices(); 588 return SpeechRecognitionManager::GetInstance()->HasAudioInputDevices();
583 } 589 }
584 590
585 bool SpeechInputExtensionManager::IsCapturingAudio() { 591 bool SpeechInputExtensionManager::IsCapturingAudio() {
586 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 592 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
587 return SpeechRecognitionManager::GetInstance()->IsCapturingAudio(); 593 return SpeechRecognitionManager::GetInstance()->IsCapturingAudio();
(...skipping 22 matching lines...) Expand all
610 void SpeechInputExtensionManager::IsRecordingOnUIThread( 616 void SpeechInputExtensionManager::IsRecordingOnUIThread(
611 const IsRecordingCallback& callback, 617 const IsRecordingCallback& callback,
612 bool result) { 618 bool result) {
613 BrowserThread::CurrentlyOn(BrowserThread::UI); 619 BrowserThread::CurrentlyOn(BrowserThread::UI);
614 callback.Run(result); 620 callback.Run(result);
615 } 621 }
616 622
617 void SpeechInputExtensionManager::StartRecording( 623 void SpeechInputExtensionManager::StartRecording(
618 content::SpeechRecognitionEventListener* listener, 624 content::SpeechRecognitionEventListener* listener,
619 net::URLRequestContextGetter* context_getter, 625 net::URLRequestContextGetter* context_getter,
620 int session_id, 626 const string16& extension_name,
621 const std::string& language, 627 const std::string& language,
622 const std::string& grammar, 628 const std::string& grammar,
623 bool filter_profanities) { 629 bool filter_profanities,
630 bool show_notification) {
624 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 631 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
625 DCHECK(!recognizer_); 632
626 recognizer_ = content::SpeechRecognizer::Create( 633 content::SpeechRecognitionSessionContext context;
627 listener, session_id, language, grammar, context_getter, 634 context.use_bubble_on_element = false;
628 filter_profanities, "", ""); 635 context.show_security_balloon = show_notification;
629 recognizer_->StartRecognition(); 636 context.context_name = extension_name;
637
638 content::SpeechRecognitionSessionConfig config;
639 // config.is_one_shot = true; // TODO(primiano) Uncomment when CL2.0 lands.
640 config.language = language;
641 config.grammar = grammar;
642 config.initial_context = context;
643 config.url_request_context_getter = context_getter;
644 config.filter_profanities = filter_profanities;
645 config.event_listener = listener;
646
647 DCHECK(!is_recognition_in_progress_);
648 SpeechRecognitionManager& manager = *SpeechRecognitionManager::GetInstance();
649 speech_recognition_session_id_ =
650 manager.CreateSession(config);
651 DCHECK_NE(speech_recognition_session_id_,
652 SpeechRecognitionManager::kSessionIDInvalid);
653 is_recognition_in_progress_ = true;
654 manager.StartSession(speech_recognition_session_id_);
630 } 655 }
631 656
632 bool SpeechInputExtensionManager::HasValidRecognizer() { 657 bool SpeechInputExtensionManager::HasValidRecognizer() {
633 return !!recognizer_; 658 if (!is_recognition_in_progress_)
659 return false;
660 return SpeechRecognitionManager::GetInstance()->IsCapturingAudio();
634 } 661 }
635 662
636 bool SpeechInputExtensionManager::Stop(const std::string& extension_id, 663 bool SpeechInputExtensionManager::Stop(const std::string& extension_id,
637 std::string* error) { 664 std::string* error) {
638 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 665 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
639 DCHECK(error); 666 DCHECK(error);
640 VLOG(1) << "Requesting stop (UI thread)"; 667 VLOG(1) << "Requesting stop (UI thread)";
641 668
642 base::AutoLock auto_lock(state_lock_); 669 base::AutoLock auto_lock(state_lock_);
643 if (state_ == kShutdown || 670 if (state_ == kShutdown ||
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
684 GetSpeechInputExtensionInterface()->StopRecording(false); 711 GetSpeechInputExtensionInterface()->StopRecording(false);
685 712
686 if (state_ == kShutdown) 713 if (state_ == kShutdown)
687 return; 714 return;
688 715
689 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 716 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
690 base::Bind(&SpeechInputExtensionManager::StopSucceededOnUIThread, this)); 717 base::Bind(&SpeechInputExtensionManager::StopSucceededOnUIThread, this));
691 } 718 }
692 719
693 void SpeechInputExtensionManager::StopRecording(bool recognition_failed) { 720 void SpeechInputExtensionManager::StopRecording(bool recognition_failed) {
694 if (recognizer_) { 721 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
695 // Recognition is already cancelled in case of failure. 722 if (!is_recognition_in_progress_)
696 // Double-cancelling leads to assertion failures. 723 return;
697 if (!recognition_failed) 724 DCHECK_NE(speech_recognition_session_id_,
698 recognizer_->AbortRecognition(); 725 SpeechRecognitionManager::kSessionIDInvalid);
699 recognizer_.release(); 726 SpeechRecognitionManager::GetInstance()->AbortSession(
700 } 727 speech_recognition_session_id_);
701 } 728 }
702 729
703 void SpeechInputExtensionManager::StopSucceededOnUIThread() { 730 void SpeechInputExtensionManager::StopSucceededOnUIThread() {
704 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 731 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
705 VLOG(1) << "Stop succeeded (UI thread)"; 732 VLOG(1) << "Stop succeeded (UI thread)";
706 733
707 base::AutoLock auto_lock(state_lock_); 734 base::AutoLock auto_lock(state_lock_);
708 if (state_ == kShutdown) 735 if (state_ == kShutdown)
709 return; 736 return;
710 737
711 std::string extension_id = extension_id_in_use_; 738 std::string extension_id = extension_id_in_use_;
712 ResetToIdleState(); 739 ResetToIdleState();
713 740
714 DCHECK(notification_.get());
715 notification_->Hide();
716
717 content::NotificationService::current()->Notify( 741 content::NotificationService::current()->Notify(
718 chrome::NOTIFICATION_EXTENSION_SPEECH_INPUT_RECORDING_STOPPED, 742 chrome::NOTIFICATION_EXTENSION_SPEECH_INPUT_RECORDING_STOPPED,
719 // Guarded by the state_ == kShutdown check. 743 // Guarded by the state_ == kShutdown check.
720 content::Source<Profile>(profile_), 744 content::Source<Profile>(profile_),
721 content::Details<std::string>(&extension_id)); 745 content::Details<std::string>(&extension_id));
722 } 746 }
723 747
724 void SpeechInputExtensionManager::OnAudioLevelsChange(int session_id, 748 void SpeechInputExtensionManager::OnAudioLevelsChange(int session_id,
725 float volume, 749 float volume,
726 float noise_volume) { 750 float noise_volume) {}
727 DCHECK_EQ(session_id, kSpeechInputSessionId);
728 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
729 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
730 base::Bind(&SpeechInputExtensionManager::SetInputVolumeOnUIThread,
731 this, volume));
732 }
733
734 void SpeechInputExtensionManager::SetInputVolumeOnUIThread(
735 float volume) {
736 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
737 DCHECK(notification_.get());
738 notification_->SetVUMeterVolume(volume);
739 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698