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/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" |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 48 | 48 |
| 49 const char kUtteranceKey[] = "utterance"; | 49 const char kUtteranceKey[] = "utterance"; |
| 50 const char kConfidenceKey[] = "confidence"; | 50 const char kConfidenceKey[] = "confidence"; |
| 51 const char kHypothesesKey[] = "hypotheses"; | 51 const char kHypothesesKey[] = "hypotheses"; |
| 52 | 52 |
| 53 const char kOnErrorEvent[] = "experimental.speechInput.onError"; | 53 const char kOnErrorEvent[] = "experimental.speechInput.onError"; |
| 54 const char kOnResultEvent[] = "experimental.speechInput.onResult"; | 54 const char kOnResultEvent[] = "experimental.speechInput.onResult"; |
| 55 const char kOnSoundStartEvent[] = "experimental.speechInput.onSoundStart"; | 55 const char kOnSoundStartEvent[] = "experimental.speechInput.onSoundStart"; |
| 56 const char kOnSoundEndEvent[] = "experimental.speechInput.onSoundEnd"; | 56 const char kOnSoundEndEvent[] = "experimental.speechInput.onSoundEnd"; |
| 57 | 57 |
| 58 // Caller id provided to the speech recognizer. Since only one extension can | 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. | 59 // be recording on the same time a constant value is enough as id. |
| 60 static const int kSpeechCallerId = 1; | 60 // TODO(primiano) this will not be valid anymore once speech input extension |
|
Satish
2012/04/17 09:25:43
'valid anymore' -> 'required'
'extension will use'
| |
| 61 // will use the SpeechRecognitionManager and not the SpeechRecognizer directly. | |
| 62 static const int kSpeechInputSessionId = 1; | |
| 61 | 63 |
| 62 // Wrap an SpeechInputExtensionManager using scoped_refptr to avoid | 64 // Wrap an SpeechInputExtensionManager using scoped_refptr to avoid |
| 63 // assertion failures on destruction because of not using release(). | 65 // assertion failures on destruction because of not using release(). |
| 64 class SpeechInputExtensionManagerWrapper : public ProfileKeyedService { | 66 class SpeechInputExtensionManagerWrapper : public ProfileKeyedService { |
| 65 public: | 67 public: |
| 66 explicit SpeechInputExtensionManagerWrapper( | 68 explicit SpeechInputExtensionManagerWrapper( |
| 67 SpeechInputExtensionManager* manager) | 69 SpeechInputExtensionManager* manager) |
| 68 : manager_(manager) {} | 70 : manager_(manager) {} |
| 69 | 71 |
| 70 virtual ~SpeechInputExtensionManagerWrapper() {} | 72 virtual ~SpeechInputExtensionManagerWrapper() {} |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 232 return speech_interface_ ? speech_interface_ : this; | 234 return speech_interface_ ? speech_interface_ : this; |
| 233 } | 235 } |
| 234 | 236 |
| 235 void SpeechInputExtensionManager::ResetToIdleState() { | 237 void SpeechInputExtensionManager::ResetToIdleState() { |
| 236 VLOG(1) << "State changed to idle. Deassociating any extensions."; | 238 VLOG(1) << "State changed to idle. Deassociating any extensions."; |
| 237 state_ = kIdle; | 239 state_ = kIdle; |
| 238 extension_id_in_use_.clear(); | 240 extension_id_in_use_.clear(); |
| 239 } | 241 } |
| 240 | 242 |
| 241 void SpeechInputExtensionManager::OnRecognitionResult( | 243 void SpeechInputExtensionManager::OnRecognitionResult( |
| 242 int caller_id, | 244 int session_id, |
| 243 const content::SpeechRecognitionResult& result) { | 245 const content::SpeechRecognitionResult& result) { |
| 244 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 246 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 245 DCHECK_EQ(caller_id, kSpeechCallerId); | 247 DCHECK_EQ(session_id, kSpeechInputSessionId); |
| 246 | 248 |
| 247 // Stopping will start the disassociation with the extension. | 249 // Stopping will start the disassociation with the extension. |
| 248 // Make a copy to report the results to the proper one. | 250 // Make a copy to report the results to the proper one. |
| 249 std::string extension_id = extension_id_in_use_; | 251 std::string extension_id = extension_id_in_use_; |
| 250 ForceStopOnIOThread(); | 252 ForceStopOnIOThread(); |
| 251 | 253 |
| 252 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 254 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 253 base::Bind(&SpeechInputExtensionManager::SetRecognitionResultOnUIThread, | 255 base::Bind(&SpeechInputExtensionManager::SetRecognitionResultOnUIThread, |
| 254 this, result, extension_id)); | 256 this, result, extension_id)); |
| 255 } | 257 } |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 277 js_hypothesis_object->SetDouble(kConfidenceKey, | 279 js_hypothesis_object->SetDouble(kConfidenceKey, |
| 278 hypothesis.confidence); | 280 hypothesis.confidence); |
| 279 } | 281 } |
| 280 | 282 |
| 281 std::string json_args; | 283 std::string json_args; |
| 282 base::JSONWriter::Write(&args, &json_args); | 284 base::JSONWriter::Write(&args, &json_args); |
| 283 VLOG(1) << "Results: " << json_args; | 285 VLOG(1) << "Results: " << json_args; |
| 284 DispatchEventToExtension(extension_id, kOnResultEvent, json_args); | 286 DispatchEventToExtension(extension_id, kOnResultEvent, json_args); |
| 285 } | 287 } |
| 286 | 288 |
| 287 void SpeechInputExtensionManager::OnRecognitionStart(int caller_id) { | 289 void SpeechInputExtensionManager::OnRecognitionStart(int session_id) { |
| 288 DCHECK_EQ(caller_id, kSpeechCallerId); | 290 DCHECK_EQ(session_id, kSpeechInputSessionId); |
| 289 } | 291 } |
| 290 | 292 |
| 291 void SpeechInputExtensionManager::OnAudioStart(int caller_id) { | 293 void SpeechInputExtensionManager::OnAudioStart(int session_id) { |
| 292 VLOG(1) << "OnAudioStart"; | 294 VLOG(1) << "OnAudioStart"; |
| 293 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 295 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 294 DCHECK_EQ(caller_id, kSpeechCallerId); | 296 DCHECK_EQ(session_id, kSpeechInputSessionId); |
| 295 | 297 |
| 296 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 298 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 297 base::Bind(&SpeechInputExtensionManager::DidStartReceivingAudioOnUIThread, | 299 base::Bind(&SpeechInputExtensionManager::DidStartReceivingAudioOnUIThread, |
| 298 this)); | 300 this)); |
| 299 } | 301 } |
| 300 | 302 |
| 301 void SpeechInputExtensionManager::OnAudioEnd(int caller_id) { | 303 void SpeechInputExtensionManager::OnAudioEnd(int session_id) { |
| 302 DCHECK_EQ(caller_id, kSpeechCallerId); | 304 DCHECK_EQ(session_id, kSpeechInputSessionId); |
| 303 } | 305 } |
| 304 | 306 |
| 305 void SpeechInputExtensionManager::OnRecognitionEnd(int caller_id) { | 307 void SpeechInputExtensionManager::OnRecognitionEnd(int session_id) { |
| 306 DCHECK_EQ(caller_id, kSpeechCallerId); | 308 DCHECK_EQ(session_id, kSpeechInputSessionId); |
| 307 } | 309 } |
| 308 | 310 |
| 309 void SpeechInputExtensionManager::DidStartReceivingAudioOnUIThread() { | 311 void SpeechInputExtensionManager::DidStartReceivingAudioOnUIThread() { |
| 310 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 312 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 311 | 313 |
| 312 base::AutoLock auto_lock(state_lock_); | 314 base::AutoLock auto_lock(state_lock_); |
| 313 if (state_ == kShutdown) | 315 if (state_ == kShutdown) |
| 314 return; | 316 return; |
| 315 | 317 |
| 316 DCHECK_EQ(state_, kStarting); | 318 DCHECK_EQ(state_, kStarting); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 334 } | 336 } |
| 335 | 337 |
| 336 VLOG(1) << "Sending start notification"; | 338 VLOG(1) << "Sending start notification"; |
| 337 content::NotificationService::current()->Notify( | 339 content::NotificationService::current()->Notify( |
| 338 chrome::NOTIFICATION_EXTENSION_SPEECH_INPUT_RECORDING_STARTED, | 340 chrome::NOTIFICATION_EXTENSION_SPEECH_INPUT_RECORDING_STARTED, |
| 339 content::Source<Profile>(profile_), | 341 content::Source<Profile>(profile_), |
| 340 content::Details<std::string>(&extension_id_in_use_)); | 342 content::Details<std::string>(&extension_id_in_use_)); |
| 341 } | 343 } |
| 342 | 344 |
| 343 void SpeechInputExtensionManager::OnRecognitionError( | 345 void SpeechInputExtensionManager::OnRecognitionError( |
| 344 int caller_id, const content::SpeechRecognitionError& error) { | 346 int session_id, const content::SpeechRecognitionError& error) { |
| 345 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 347 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 346 DCHECK_EQ(caller_id, kSpeechCallerId); | 348 DCHECK_EQ(session_id, kSpeechInputSessionId); |
| 347 VLOG(1) << "OnRecognitionError: " << error.code; | 349 VLOG(1) << "OnRecognitionError: " << error.code; |
| 348 | 350 |
| 349 base::AutoLock auto_lock(state_lock_); | 351 base::AutoLock auto_lock(state_lock_); |
| 350 if (state_ == kShutdown) | 352 if (state_ == kShutdown) |
| 351 return; | 353 return; |
| 352 | 354 |
| 353 // Release the recognizer object. | 355 // Release the recognizer object. |
| 354 GetSpeechInputExtensionInterface()->StopRecording(true); | 356 GetSpeechInputExtensionInterface()->StopRecording(true); |
| 355 | 357 |
| 356 std::string event_error_code; | 358 std::string event_error_code; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 394 } | 396 } |
| 395 | 397 |
| 396 if (!event_error_code.empty()) { | 398 if (!event_error_code.empty()) { |
| 397 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 399 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 398 base::Bind(&SpeechInputExtensionManager::DispatchError, | 400 base::Bind(&SpeechInputExtensionManager::DispatchError, |
| 399 this, event_error_code, report_to_event)); | 401 this, event_error_code, report_to_event)); |
| 400 } | 402 } |
| 401 } | 403 } |
| 402 | 404 |
| 403 void SpeechInputExtensionManager::OnEnvironmentEstimationComplete( | 405 void SpeechInputExtensionManager::OnEnvironmentEstimationComplete( |
| 404 int caller_id) { | 406 int session_id) { |
| 405 DCHECK_EQ(caller_id, kSpeechCallerId); | 407 DCHECK_EQ(session_id, kSpeechInputSessionId); |
| 406 } | 408 } |
| 407 | 409 |
| 408 void SpeechInputExtensionManager::OnSoundStart(int caller_id) { | 410 void SpeechInputExtensionManager::OnSoundStart(int session_id) { |
| 409 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 411 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 410 DCHECK_EQ(caller_id, kSpeechCallerId); | 412 DCHECK_EQ(session_id, kSpeechInputSessionId); |
| 411 VLOG(1) << "OnSoundStart"; | 413 VLOG(1) << "OnSoundStart"; |
| 412 | 414 |
| 413 std::string json_args; | 415 std::string json_args; |
| 414 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 416 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 415 base::Bind(&SpeechInputExtensionManager::DispatchEventToExtension, | 417 base::Bind(&SpeechInputExtensionManager::DispatchEventToExtension, |
| 416 this, extension_id_in_use_, std::string(kOnSoundStartEvent), | 418 this, extension_id_in_use_, std::string(kOnSoundStartEvent), |
| 417 json_args)); | 419 json_args)); |
| 418 } | 420 } |
| 419 | 421 |
| 420 void SpeechInputExtensionManager::OnSoundEnd(int caller_id) { | 422 void SpeechInputExtensionManager::OnSoundEnd(int session_id) { |
| 421 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 423 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 422 DCHECK_EQ(caller_id, kSpeechCallerId); | 424 DCHECK_EQ(session_id, kSpeechInputSessionId); |
| 423 VLOG(1) << "OnSoundEnd"; | 425 VLOG(1) << "OnSoundEnd"; |
| 424 | 426 |
| 425 std::string json_args; | 427 std::string json_args; |
| 426 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 428 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 427 base::Bind(&SpeechInputExtensionManager::DispatchEventToExtension, | 429 base::Bind(&SpeechInputExtensionManager::DispatchEventToExtension, |
| 428 this, extension_id_in_use_, std::string(kOnSoundEndEvent), | 430 this, extension_id_in_use_, std::string(kOnSoundEndEvent), |
| 429 json_args)); | 431 json_args)); |
| 430 } | 432 } |
| 431 | 433 |
| 432 void SpeechInputExtensionManager::DispatchEventToExtension( | 434 void SpeechInputExtensionManager::DispatchEventToExtension( |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 558 } | 560 } |
| 559 | 561 |
| 560 if (GetSpeechInputExtensionInterface()->IsCapturingAudio()) { | 562 if (GetSpeechInputExtensionInterface()->IsCapturingAudio()) { |
| 561 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 563 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 562 base::Bind(&SpeechInputExtensionManager::DispatchError, this, | 564 base::Bind(&SpeechInputExtensionManager::DispatchError, this, |
| 563 std::string(kErrorRecordingDeviceInUse), false)); | 565 std::string(kErrorRecordingDeviceInUse), false)); |
| 564 return; | 566 return; |
| 565 } | 567 } |
| 566 | 568 |
| 567 GetSpeechInputExtensionInterface()->StartRecording( | 569 GetSpeechInputExtensionInterface()->StartRecording( |
| 568 this, context_getter, kSpeechCallerId, language, grammar, | 570 this, context_getter, kSpeechInputSessionId, language, grammar, |
| 569 filter_profanities); | 571 filter_profanities); |
| 570 } | 572 } |
| 571 | 573 |
| 572 bool SpeechInputExtensionManager::HasAudioInputDevices() { | 574 bool SpeechInputExtensionManager::HasAudioInputDevices() { |
| 573 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 575 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 574 return SpeechRecognitionManager::GetInstance()->HasAudioInputDevices(); | 576 return SpeechRecognitionManager::GetInstance()->HasAudioInputDevices(); |
| 575 } | 577 } |
| 576 | 578 |
| 577 bool SpeechInputExtensionManager::IsCapturingAudio() { | 579 bool SpeechInputExtensionManager::IsCapturingAudio() { |
| 578 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 580 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 602 void SpeechInputExtensionManager::IsRecordingOnUIThread( | 604 void SpeechInputExtensionManager::IsRecordingOnUIThread( |
| 603 const IsRecordingCallback& callback, | 605 const IsRecordingCallback& callback, |
| 604 bool result) { | 606 bool result) { |
| 605 BrowserThread::CurrentlyOn(BrowserThread::UI); | 607 BrowserThread::CurrentlyOn(BrowserThread::UI); |
| 606 callback.Run(result); | 608 callback.Run(result); |
| 607 } | 609 } |
| 608 | 610 |
| 609 void SpeechInputExtensionManager::StartRecording( | 611 void SpeechInputExtensionManager::StartRecording( |
| 610 content::SpeechRecognitionEventListener* listener, | 612 content::SpeechRecognitionEventListener* listener, |
| 611 net::URLRequestContextGetter* context_getter, | 613 net::URLRequestContextGetter* context_getter, |
| 612 int caller_id, | 614 int session_id, |
| 613 const std::string& language, | 615 const std::string& language, |
| 614 const std::string& grammar, | 616 const std::string& grammar, |
| 615 bool filter_profanities) { | 617 bool filter_profanities) { |
| 616 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 618 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 617 DCHECK(!recognizer_); | 619 DCHECK(!recognizer_); |
| 618 recognizer_ = content::SpeechRecognizer::Create( | 620 recognizer_ = content::SpeechRecognizer::Create( |
| 619 listener, caller_id, language, grammar, context_getter, | 621 listener, session_id, language, grammar, context_getter, |
| 620 filter_profanities, "", ""); | 622 filter_profanities, "", ""); |
| 621 recognizer_->StartRecognition(); | 623 recognizer_->StartRecognition(); |
| 622 } | 624 } |
| 623 | 625 |
| 624 bool SpeechInputExtensionManager::HasValidRecognizer() { | 626 bool SpeechInputExtensionManager::HasValidRecognizer() { |
| 625 return !!recognizer_; | 627 return !!recognizer_; |
| 626 } | 628 } |
| 627 | 629 |
| 628 bool SpeechInputExtensionManager::Stop(const std::string& extension_id, | 630 bool SpeechInputExtensionManager::Stop(const std::string& extension_id, |
| 629 std::string* error) { | 631 std::string* error) { |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 706 DCHECK(notification_.get()); | 708 DCHECK(notification_.get()); |
| 707 notification_->Hide(); | 709 notification_->Hide(); |
| 708 | 710 |
| 709 content::NotificationService::current()->Notify( | 711 content::NotificationService::current()->Notify( |
| 710 chrome::NOTIFICATION_EXTENSION_SPEECH_INPUT_RECORDING_STOPPED, | 712 chrome::NOTIFICATION_EXTENSION_SPEECH_INPUT_RECORDING_STOPPED, |
| 711 // Guarded by the state_ == kShutdown check. | 713 // Guarded by the state_ == kShutdown check. |
| 712 content::Source<Profile>(profile_), | 714 content::Source<Profile>(profile_), |
| 713 content::Details<std::string>(&extension_id)); | 715 content::Details<std::string>(&extension_id)); |
| 714 } | 716 } |
| 715 | 717 |
| 716 void SpeechInputExtensionManager::OnAudioLevelsChange(int caller_id, | 718 void SpeechInputExtensionManager::OnAudioLevelsChange(int session_id, |
| 717 float volume, | 719 float volume, |
| 718 float noise_volume) { | 720 float noise_volume) { |
| 719 DCHECK_EQ(caller_id, kSpeechCallerId); | 721 DCHECK_EQ(session_id, kSpeechInputSessionId); |
| 720 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 722 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 721 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 723 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 722 base::Bind(&SpeechInputExtensionManager::SetInputVolumeOnUIThread, | 724 base::Bind(&SpeechInputExtensionManager::SetInputVolumeOnUIThread, |
| 723 this, volume)); | 725 this, volume)); |
| 724 } | 726 } |
| 725 | 727 |
| 726 void SpeechInputExtensionManager::SetInputVolumeOnUIThread( | 728 void SpeechInputExtensionManager::SetInputVolumeOnUIThread( |
| 727 float volume) { | 729 float volume) { |
| 728 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 730 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 729 DCHECK(notification_.get()); | 731 DCHECK(notification_.get()); |
| 730 notification_->SetVUMeterVolume(volume); | 732 notification_->SetVUMeterVolume(volume); |
| 731 } | 733 } |
| OLD | NEW |