Commit 011cfc7d authored by primiano@chromium.org's avatar primiano@chromium.org

SpeechInputExtensionManager now interface (exclusively) with...

SpeechInputExtensionManager now interface (exclusively) with SpeechRecognitionManagerDelegate (Speech CL1.11).

- The tray icon and balloon handing has been moved from speech_input_extensions_manager to chrome_speech_recognition_manager_delegate, since that code (tray icon) will be used also for continuous recognition.
- Removed the SpeechRecognizer interface from /content/public (thus de-virtualized and refcounted the SpeechRecognizerImpl)

BUG=116954
TEST=none

Review URL: https://chromiumcodereview.appspot.com/10377082

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@138498 0039d316-1c4b-4281-b951-d872f2087c98
parent 8bf9ce70
......@@ -13,6 +13,8 @@
#include "content/public/browser/speech_recognition_manager_delegate.h"
#include "content/public/browser/speech_recognition_session_config.h"
class SpeechRecognitionTrayIconController;
namespace speech {
// This is Chrome's implementation of the SpeechRecognitionManagerDelegate
......@@ -69,7 +71,12 @@ class ChromeSpeechRecognitionManagerDelegate
// (which is copied into |last_session_config_|). Used for "try again".
void RestartLastSession();
// Lazy initializers for bubble and tray icon controller.
SpeechRecognitionBubbleController* GetBubbleController();
SpeechRecognitionTrayIconController* GetTrayIconController();
scoped_refptr<SpeechRecognitionBubbleController> bubble_controller_;
scoped_refptr<SpeechRecognitionTrayIconController> tray_icon_controller_;
scoped_refptr<OptionalRequestInfo> optional_request_info_;
scoped_ptr<content::SpeechRecognitionSessionConfig> last_session_config_;
......
......@@ -23,6 +23,10 @@ namespace net {
class URLRequestContextGetter;
}
namespace {
const int kSessionIDForTests = 0;
}
// Mock class used to test the extension speech input API.
class SpeechInputExtensionApiTest : public ExtensionApiTest,
public SpeechInputExtensionInterface {
......@@ -77,10 +81,11 @@ class SpeechInputExtensionApiTest : public ExtensionApiTest,
virtual void StartRecording(
content::SpeechRecognitionEventListener* listener,
net::URLRequestContextGetter* context_getter,
int session_id,
const string16& extension_name,
const std::string& language,
const std::string& grammar,
bool filter_profanities) OVERRIDE;
bool filter_profanities,
bool show_notification) OVERRIDE;
virtual void StopRecording(bool recognition_failed) OVERRIDE;
......@@ -107,7 +112,7 @@ class SpeechInputExtensionApiTest : public ExtensionApiTest,
};
private:
void ProvideResults(int session_id);
void ProvideResults();
bool recording_devices_available_;
bool recognizer_is_valid_;
......@@ -131,10 +136,11 @@ SpeechInputExtensionApiTest::~SpeechInputExtensionApiTest() {
void SpeechInputExtensionApiTest::StartRecording(
content::SpeechRecognitionEventListener* listener,
net::URLRequestContextGetter* context_getter,
int session_id,
const string16& extension_name,
const std::string& language,
const std::string& grammar,
bool filter_profanities) {
bool filter_profanities,
bool show_notification) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
recognizer_is_valid_ = true;
......@@ -143,7 +149,7 @@ void SpeechInputExtensionApiTest::StartRecording(
FROM_HERE,
base::Bind(&SpeechInputExtensionManager::OnAudioStart,
GetManager(),
session_id),
kSessionIDForTests),
base::TimeDelta());
// Notify sound start in the input device.
......@@ -151,16 +157,14 @@ void SpeechInputExtensionApiTest::StartRecording(
FROM_HERE,
base::Bind(&SpeechInputExtensionManager::OnSoundStart,
GetManager(),
session_id),
kSessionIDForTests),
base::TimeDelta());
if (result_delay_ms_ != kDontDispatchCall) {
// Dispatch the recognition results.
MessageLoop::current()->PostDelayedTask(
FROM_HERE,
base::Bind(&SpeechInputExtensionApiTest::ProvideResults,
this,
session_id),
base::Bind(&SpeechInputExtensionApiTest::ProvideResults, this),
base::TimeDelta::FromMilliseconds(result_delay_ms_));
}
}
......@@ -170,18 +174,19 @@ void SpeechInputExtensionApiTest::StopRecording(bool recognition_failed) {
recognizer_is_valid_ = false;
}
void SpeechInputExtensionApiTest::ProvideResults(int session_id) {
void SpeechInputExtensionApiTest::ProvideResults() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (next_error_ != content::SPEECH_RECOGNITION_ERROR_NONE) {
GetManager()->OnRecognitionError(
session_id, content::SpeechRecognitionError(next_error_));
kSessionIDForTests, content::SpeechRecognitionError(next_error_));
return;
}
GetManager()->OnSoundEnd(session_id);
GetManager()->OnAudioEnd(session_id);
GetManager()->OnRecognitionResult(session_id, next_result_);
GetManager()->OnSoundEnd(kSessionIDForTests);
GetManager()->OnAudioEnd(kSessionIDForTests);
GetManager()->OnRecognitionResult(kSessionIDForTests, next_result_);
GetManager()->OnRecognitionEnd(kSessionIDForTests);
}
// Every test should leave the manager in the idle state when finished.
......
......@@ -11,18 +11,18 @@
#include "base/callback_forward.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/string16.h"
#include "base/synchronization/lock.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/speech_recognition_event_listener.h"
class Profile;
class SpeechRecognitionTrayIconController;
namespace content {
class NotificationRegistrar;
struct SpeechRecognitionError;
class SpeechRecognitionManager;
struct SpeechRecognitionResult;
class SpeechRecognizer;
}
namespace net {
......@@ -39,10 +39,11 @@ class SpeechInputExtensionInterface {
virtual void StartRecording(
content::SpeechRecognitionEventListener* listener,
net::URLRequestContextGetter* context_getter,
int session_id,
const string16& extension_name,
const std::string& language,
const std::string& grammar,
bool filter_profanities) = 0;
bool filter_profanities,
bool show_notification) = 0;
virtual void StopRecording(bool recognition_failed) = 0;
virtual bool HasAudioInputDevices() = 0;
......@@ -143,19 +144,22 @@ class SpeechInputExtensionManager
virtual void StartRecording(
content::SpeechRecognitionEventListener* listener,
net::URLRequestContextGetter* context_getter,
int session_id,
const string16& extension_name,
const std::string& language,
const std::string& grammar,
bool filter_profanities) OVERRIDE;
bool filter_profanities,
bool show_notification) OVERRIDE;
virtual void StopRecording(bool recognition_failed) OVERRIDE;
// Internal methods.
void StartOnIOThread(
net::URLRequestContextGetter* context_getter,
scoped_refptr<net::URLRequestContextGetter> context_getter,
const string16& extension_name,
const std::string& language,
const std::string& grammar,
bool filter_profanities);
bool filter_profanities,
bool show_notification);
void ForceStopOnIOThread();
void IsRecordingOnIOThread(const IsRecordingCallback& callback);
......@@ -172,7 +176,6 @@ class SpeechInputExtensionManager
const std::string& json_args);
void ExtensionUnloaded(const std::string& extension_id);
void SetInputVolumeOnUIThread(float volume);
void ResetToIdleState();
virtual ~SpeechInputExtensionManager();
......@@ -196,10 +199,10 @@ class SpeechInputExtensionManager
// Used in the UI thread.
scoped_ptr<content::NotificationRegistrar> registrar_;
SpeechInputExtensionInterface* speech_interface_;
scoped_refptr<SpeechRecognitionTrayIconController> notification_;
// Used in the IO thread.
scoped_refptr<content::SpeechRecognizer> recognizer_;
bool is_recognition_in_progress_;
int speech_recognition_session_id_;
};
#endif // CHROME_BROWSER_SPEECH_SPEECH_INPUT_EXTENSION_MANAGER_H_
......@@ -327,6 +327,12 @@ void SpeechRecognitionManagerImpl::AbortAllSessionsForListener(
void SpeechRecognitionManagerImpl::DispatchEvent(int session_id,
FSMEvent event) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
// There are some corner cases in which the session might be deleted (due to
// an EndRecognition event) between a request (e.g. Abort) and its dispatch.
if (!SessionExists(session_id))
return;
const Session& session = GetSession(session_id);
FSMState session_state = GetSessionState(session_id);
DCHECK_LE(session_state, SESSION_STATE_MAX_VALUE);
......
......@@ -12,7 +12,6 @@
#include "content/browser/speech/google_one_shot_remote_engine.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/speech_recognition_event_listener.h"
#include "content/public/browser/speech_recognizer.h"
#include "content/public/common/speech_recognition_error.h"
#include "content/public/common/speech_recognition_grammar.h"
#include "content/public/common/speech_recognition_result.h"
......@@ -24,7 +23,6 @@ using content::SpeechRecognitionError;
using content::SpeechRecognitionEventListener;
using content::SpeechRecognitionGrammar;
using content::SpeechRecognitionResult;
using content::SpeechRecognizer;
using media::AudioInputController;
using media::AudioManager;
using media::AudioParameters;
......@@ -68,41 +66,6 @@ void KeepAudioControllerRefcountedForDtor(scoped_refptr<AudioInputController>) {
} // namespace
// TODO(primiano) Create(...) is transitional (until we fix speech input
// extensions) and should be removed soon. The manager should be the only one
// knowing the existence of SpeechRecognizer(Impl), thus the only one in charge
// of instantiating it.
SpeechRecognizer* SpeechRecognizer::Create(
SpeechRecognitionEventListener* listener,
int session_id,
const std::string& language,
const std::string& grammar,
net::URLRequestContextGetter* context_getter,
bool filter_profanities,
const std::string& hardware_info,
const std::string& origin_url) {
speech::SpeechRecognitionEngineConfig remote_engine_config;
remote_engine_config.language = language;
if (!grammar.empty())
remote_engine_config.grammars.push_back(SpeechRecognitionGrammar(grammar));
remote_engine_config.audio_sample_rate =
speech::SpeechRecognizerImpl::kAudioSampleRate;
remote_engine_config.audio_num_bits_per_sample =
speech::SpeechRecognizerImpl::kNumBitsPerAudioSample;
remote_engine_config.filter_profanities = filter_profanities;
remote_engine_config.hardware_info = hardware_info;
remote_engine_config.origin_url = origin_url;
// SpeechRecognizerImpl takes ownership of google_remote_engine.
speech::GoogleOneShotRemoteEngine* google_remote_engine =
new speech::GoogleOneShotRemoteEngine(context_getter);
google_remote_engine->SetConfig(remote_engine_config);
return new speech::SpeechRecognizerImpl(listener,
session_id,
google_remote_engine);
}
namespace speech {
const int SpeechRecognizerImpl::kAudioSampleRate = 16000;
......
......@@ -11,7 +11,6 @@
#include "base/memory/scoped_ptr.h"
#include "content/browser/speech/endpointer/endpointer.h"
#include "content/browser/speech/speech_recognition_engine.h"
#include "content/public/browser/speech_recognizer.h"
#include "content/public/common/speech_recognition_error.h"
#include "content/public/common/speech_recognition_result.h"
#include "media/audio/audio_input_controller.h"
......@@ -27,15 +26,13 @@ class AudioManager;
namespace speech {
// TODO(primiano) Next CL: Remove the Impl suffix and the exported
// /content/public/browser/speech_recognizer.h interface since this class should
// not be visible outside (currently we need it for speech input extension API).
// TODO(primiano) Next CL: Remove the Impl suffix.
// Handles speech recognition for a session (identified by |session_id|), taking
// care of audio capture, silence detection/endpointer and interaction with the
// SpeechRecognitionEngine.
class CONTENT_EXPORT SpeechRecognizerImpl
: public NON_EXPORTED_BASE(content::SpeechRecognizer),
: public base::RefCountedThreadSafe<SpeechRecognizerImpl>,
public media::AudioInputController::EventHandler,
public NON_EXPORTED_BASE(SpeechRecognitionEngineDelegate) {
public:
......@@ -50,18 +47,15 @@ class CONTENT_EXPORT SpeechRecognizerImpl
int session_id,
SpeechRecognitionEngine* engine);
// content::SpeechRecognizer methods.
virtual void StartRecognition() OVERRIDE;
virtual void AbortRecognition() OVERRIDE;
virtual void StopAudioCapture() OVERRIDE;
virtual bool IsActive() const OVERRIDE;
virtual bool IsCapturingAudio() const OVERRIDE;
void StartRecognition();
void AbortRecognition();
void StopAudioCapture();
bool IsActive() const;
bool IsCapturingAudio() const;
const SpeechRecognitionEngine& recognition_engine() const;
protected:
virtual ~SpeechRecognizerImpl();
private:
friend class base::RefCountedThreadSafe<SpeechRecognizerImpl>;
friend class SpeechRecognizerImplTest;
enum FSMState {
......@@ -96,6 +90,8 @@ class CONTENT_EXPORT SpeechRecognizerImpl
content::SpeechRecognitionError engine_error;
};
virtual ~SpeechRecognizerImpl();
// Entry point for pushing any new external event into the recognizer FSM.
void DispatchEvent(const FSMEventArgs& event_args);
......
......@@ -139,8 +139,8 @@
'public/browser/speech_recognition_preferences.h',
'public/browser/speech_recognition_session_config.cc',
'public/browser/speech_recognition_session_config.h',
'public/browser/speech_recognition_session_context.cc',
'public/browser/speech_recognition_session_context.h',
'public/browser/speech_recognizer.h',
'public/browser/trace_controller.h',
'public/browser/trace_subscriber.h',
'public/browser/user_metrics.h',
......
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/public/browser/speech_recognition_session_context.h"
namespace content {
SpeechRecognitionSessionContext::SpeechRecognitionSessionContext()
: render_process_id(0),
render_view_id(0),
render_request_id(0),
requested_by_page_element(true),
is_first_request_for_context(false) {
}
SpeechRecognitionSessionContext::~SpeechRecognitionSessionContext() {
}
} // namespace content
......@@ -6,6 +6,7 @@
#define CONTENT_PUBLIC_BROWSER_SPEECH_RECOGNITION_SESSION_CONTEXT_H_
#pragma once
#include "base/string16.h"
#include "content/common/content_export.h"
#include "ui/gfx/rect.h"
......@@ -21,18 +22,32 @@ namespace content {
// SpeechRecognitionManager::GetSessionContext and
// SpeechRecognitionManager::LookupSessionByContext methods).
struct CONTENT_EXPORT SpeechRecognitionSessionContext {
SpeechRecognitionSessionContext()
: render_process_id(0),
render_view_id(0),
render_request_id(0),
js_handle_id(0) {}
~SpeechRecognitionSessionContext() {}
SpeechRecognitionSessionContext();
~SpeechRecognitionSessionContext();
int render_process_id;
int render_view_id;
int render_request_id;
int js_handle_id;
// Determines whether recognition was requested by a page element (in which
// case its coordinates are passed in |element_rect|).
bool requested_by_page_element;
// The coordinates of the page element for placing the bubble (valid only when
// |requested_by_page_element| = true).
gfx::Rect element_rect;
// Determines whether this is the first time that this context (identified by
// |context_name|) is requesting a recognition.
// TODO(primiano) This is really temporary, remove after CL1.12 which will
// refactor SpeechRecognitionPreferences and move this check entirely whithin
// chrome, without involving content.
bool is_first_request_for_context;
// A texual description of the context (website, extension name) that is
// requesting recognition, for prompting security notifications to the user.
string16 context_name;
};
} // namespace content
......
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_PUBLIC_BROWSER_SPEECH_RECOGNIZER_H_
#define CONTENT_PUBLIC_BROWSER_SPEECH_RECOGNIZER_H_
#pragma once
#include <string>
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
namespace net {
class URLRequestContextGetter;
}
namespace content {
class SpeechRecognitionEventListener;
// Records audio, sends recorded audio to server and translates server response
// to recognition result.
// TODO(primiano) remove this public interface as soon as we fix speech input
// extensions.
class SpeechRecognizer : public base::RefCountedThreadSafe<SpeechRecognizer> {
public:
CONTENT_EXPORT static SpeechRecognizer* Create(
SpeechRecognitionEventListener* event_listener,
int session_id,
const std::string& language,
const std::string& grammar,
net::URLRequestContextGetter* context_getter,
bool filter_profanities,
const std::string& hardware_info,
const std::string& origin_url);
// Starts audio recording and the recognition process. The same
// SpeechRecognizer instance can be used multiple times for speech recognition
// though each recognition request can be made only after the previous one
// completes (i.e. after receiving
// SpeechRecognitionEventListener::OnRecognitionEnd).
virtual void StartRecognition() = 0;
// Stops recording audio and cancels recognition. Any audio recorded so far
// gets discarded.
virtual void AbortRecognition() = 0;
// Stops recording audio and finalizes recognition, possibly getting results.
virtual void StopAudioCapture() = 0;
// Checks wether the recognizer is active, that is, either capturing audio
// or waiting for a result.
virtual bool IsActive() const = 0;
// Checks whether the recognizer is capturing audio.
virtual bool IsCapturingAudio() const = 0;
protected:
friend class base::RefCountedThreadSafe<SpeechRecognizer>;
virtual ~SpeechRecognizer() {}
};
} // namespace content
#endif // CONTENT_PUBLIC_BROWSER_SPEECH_RECOGNIZER_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment