summaryrefslogtreecommitdiffstats
path: root/content/browser
diff options
context:
space:
mode:
authortommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-12 21:50:00 +0000
committertommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-12 21:50:00 +0000
commit2e77cb39b4b2760c6aa15fb194355cc429f9cb8a (patch)
tree5e90a41a0c15409cee0fca52719187b2025a6dc9 /content/browser
parent25db386820026afcaf815b8e9290817146be111e (diff)
downloadchromium_src-2e77cb39b4b2760c6aa15fb194355cc429f9cb8a.zip
chromium_src-2e77cb39b4b2760c6aa15fb194355cc429f9cb8a.tar.gz
chromium_src-2e77cb39b4b2760c6aa15fb194355cc429f9cb8a.tar.bz2
Remove the AudioManager singleton.
Unit tests now instantiate their own AudioManager and can choose to use the default one or provide their own mock implementation without having to worry about conflicting with the singleton. The teardown sequence of the AudioManager and its thread has been cleaned up significantly and I don't think it has been completely tested before as the audio thread was terminated before all objects that belonged to the thread had a chance to do cleanup. The AudioManager unit tests do not use the actual audio thread, so this part seems to have been left out. In Chrome, the AudioManager instance is now owned by BrowserProcessImpl and always constructed on the UI thread. This instance is then shared in the same way that several other 'manager' type objects are shared to 'content' code, via content::ResourceContext. Audio specific classes do though receive a direct pointer to the AudioManager and are required to do proper reference counting if they need to hold onto the instance. I chose to use the ResourceContext rather than direct use of g_browser_process to avoid requiring another singleton when writing relatively simple tests that touch the AudioManager. I added a couple of safeguards to guard against future regressions: - Not more than one instance of the AudioManager should be created. - The AudioManager should not be addrefed by its own thread. This can basically become a circular reference and prevent deterministic shutdown. Reviewers: Of course you're free to review everything, but here's the breakdown in terms of the bare minimum from the standpoint of "Owners approval". I'm asking Henrik to be the main reviewer of the entire patch (sorry!). Henrik: Everything minus the below, but it would be great if you could take a look at the whole thing, specifically media/audio. Pawel: I'd like you to take a generic look at this approach. The key areas as far as the singleton itself goes are in media/audio/audio_manager[_base].* and chrome/browser/browser_process*.* Satish: content/browser/speech/* media/audio/audio_manager_base.* (new reference counting code) Andrew: content/browser/renderer_host/media/* content/renderer/media/webrtc_audio_device_unittest.cc (Owner) Avi: content/browser/renderer_host/render_process_host_impl.cc content/browser/resource_context.* William: chrome/browser/profiles/profile_io_data.cc chrome/browser/browser_process*.* Robert: This is basically a heads up. I hope that I didn't break the OpenBSD implementation, but unfortunately I have no way of knowing for sure. Shijing: Please take a look at AudioManagerLinux. I replaced the set of active streams with a simple counter. BUG=105249 TEST=content_unittests, media_unittests, browser_tests. Review URL: http://codereview.chromium.org/8818012 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@114084 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser')
-rw-r--r--content/browser/renderer_host/media/audio_input_device_manager.cc7
-rw-r--r--content/browser/renderer_host/media/audio_input_device_manager.h5
-rw-r--r--content/browser/renderer_host/media/audio_input_device_manager_unittest.cc52
-rw-r--r--content/browser/renderer_host/media/audio_input_renderer_host.cc1
-rw-r--r--content/browser/renderer_host/media/audio_renderer_host.cc15
-rw-r--r--content/browser/renderer_host/media/audio_renderer_host_unittest.cc28
-rw-r--r--content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc6
-rw-r--r--content/browser/renderer_host/media/media_stream_manager.cc9
-rw-r--r--content/browser/renderer_host/media/media_stream_manager.h6
-rw-r--r--content/browser/renderer_host/media/video_capture_host_unittest.cc7
-rw-r--r--content/browser/renderer_host/render_process_host_impl.cc92
-rw-r--r--content/browser/resource_context.cc16
-rw-r--r--content/browser/resource_context.h5
-rw-r--r--content/browser/speech/speech_input_browsertest.cc51
-rw-r--r--content/browser/speech/speech_input_dispatcher_host.cc11
-rw-r--r--content/browser/speech/speech_input_dispatcher_host.h8
-rw-r--r--content/browser/speech/speech_input_manager.cc55
-rw-r--r--content/browser/speech/speech_input_manager.h15
-rw-r--r--content/browser/speech/speech_recognizer.cc7
-rw-r--r--content/browser/speech/speech_recognizer.h4
-rw-r--r--content/browser/speech/speech_recognizer_unittest.cc10
21 files changed, 266 insertions, 144 deletions
diff --git a/content/browser/renderer_host/media/audio_input_device_manager.cc b/content/browser/renderer_host/media/audio_input_device_manager.cc
index 08469bf..b664090 100644
--- a/content/browser/renderer_host/media/audio_input_device_manager.cc
+++ b/content/browser/renderer_host/media/audio_input_device_manager.cc
@@ -21,9 +21,10 @@ const char AudioInputDeviceManager::kInvalidDeviceId[] = "";
// Starting id for the first capture session.
const int kFirstSessionId = AudioInputDeviceManager::kFakeOpenSessionId + 1;
-AudioInputDeviceManager::AudioInputDeviceManager()
+AudioInputDeviceManager::AudioInputDeviceManager(AudioManager* audio_manager)
: listener_(NULL),
- next_capture_session_id_(kFirstSessionId) {
+ next_capture_session_id_(kFirstSessionId),
+ audio_manager_(audio_manager) {
}
AudioInputDeviceManager::~AudioInputDeviceManager() {
@@ -46,7 +47,7 @@ void AudioInputDeviceManager::EnumerateDevices() {
DCHECK(listener_);
media::AudioDeviceNames device_names;
- AudioManager::GetAudioManager()->GetAudioInputDeviceNames(&device_names);
+ audio_manager_->GetAudioInputDeviceNames(&device_names);
StreamDeviceInfoArray* devices = new StreamDeviceInfoArray;
for (media::AudioDeviceNames::iterator it = device_names.begin();
diff --git a/content/browser/renderer_host/media/audio_input_device_manager.h b/content/browser/renderer_host/media/audio_input_device_manager.h
index e861499..2f21583 100644
--- a/content/browser/renderer_host/media/audio_input_device_manager.h
+++ b/content/browser/renderer_host/media/audio_input_device_manager.h
@@ -20,6 +20,8 @@
#include "content/common/media/media_stream_options.h"
#include "media/audio/audio_device_name.h"
+class AudioManager;
+
namespace media_stream {
class AudioInputDeviceManagerEventHandler;
@@ -34,7 +36,7 @@ class CONTENT_EXPORT AudioInputDeviceManager : public MediaStreamProvider {
static const int kInvalidSessionId;
static const char kInvalidDeviceId[];
- AudioInputDeviceManager();
+ explicit AudioInputDeviceManager(AudioManager* audio_manager);
virtual ~AudioInputDeviceManager();
// MediaStreamProvider implementation, called on IO thread.
@@ -64,6 +66,7 @@ class CONTENT_EXPORT AudioInputDeviceManager : public MediaStreamProvider {
EventHandlerMap event_handlers_;
typedef std::map<int, media::AudioDeviceName> AudioInputDeviceMap;
AudioInputDeviceMap devices_;
+ scoped_refptr<AudioManager> audio_manager_;
DISALLOW_COPY_AND_ASSIGN(AudioInputDeviceManager);
};
diff --git a/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc b/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
index e36ff92..337d655 100644
--- a/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
+++ b/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
@@ -14,13 +14,13 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-using ::testing::_;
-using ::testing::AnyNumber;
-using ::testing::InSequence;
-using ::testing::Return;
using content::BrowserThread;
-
using content::BrowserThreadImpl;
+using media_stream::AudioInputDeviceManager;
+using testing::_;
+using testing::AnyNumber;
+using testing::InSequence;
+using testing::Return;
namespace media_stream {
@@ -80,26 +80,23 @@ class MockAudioInputDeviceManagerEventHandler
DISALLOW_COPY_AND_ASSIGN(MockAudioInputDeviceManagerEventHandler);
};
-// Returns true if machine has audio input device, else returns false.
-static bool CanRunAudioInputDeviceTests() {
- AudioManager* audio_manager = AudioManager::GetAudioManager();
- if (!audio_manager)
- return false;
-
- return audio_manager->HasAudioInputDevices();
-}
-
ACTION_P(ExitMessageLoop, message_loop) {
message_loop->PostTask(FROM_HERE, MessageLoop::QuitClosure());
}
-class AudioInputDeviceManagerTest: public testing::Test {
+class AudioInputDeviceManagerTest : public testing::Test {
public:
AudioInputDeviceManagerTest()
: message_loop_(),
io_thread_(),
manager_(),
- audio_input_listener_() {}
+ audio_input_listener_() {
+ }
+
+ // Returns true iff machine has an audio input device.
+ bool CanRunAudioInputDeviceTests() {
+ return audio_manager_->HasAudioInputDevices();
+ }
protected:
virtual void SetUp() {
@@ -107,7 +104,9 @@ class AudioInputDeviceManagerTest: public testing::Test {
message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO));
io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
message_loop_.get()));
- manager_.reset(new media_stream::AudioInputDeviceManager());
+ audio_manager_ = AudioManager::Create();
+
+ manager_.reset(new AudioInputDeviceManager(audio_manager_));
audio_input_listener_.reset(new MockAudioInputDeviceManagerListener());
manager_->Register(audio_input_listener_.get());
@@ -129,6 +128,7 @@ class AudioInputDeviceManagerTest: public testing::Test {
scoped_ptr<BrowserThreadImpl> io_thread_;
scoped_ptr<AudioInputDeviceManager> manager_;
scoped_ptr<MockAudioInputDeviceManagerListener> audio_input_listener_;
+ scoped_refptr<AudioManager> audio_manager_;
private:
DISALLOW_COPY_AND_ASSIGN(AudioInputDeviceManagerTest);
@@ -138,6 +138,9 @@ class AudioInputDeviceManagerTest: public testing::Test {
TEST_F(AudioInputDeviceManagerTest, OpenAndCloseDevice) {
if (!CanRunAudioInputDeviceTests())
return;
+
+ ASSERT_FALSE(audio_input_listener_->devices_.empty());
+
InSequence s;
for (StreamDeviceInfoArray::const_iterator iter =
@@ -162,6 +165,9 @@ TEST_F(AudioInputDeviceManagerTest, OpenAndCloseDevice) {
TEST_F(AudioInputDeviceManagerTest, OpenMultipleDevices) {
if (!CanRunAudioInputDeviceTests())
return;
+
+ ASSERT_FALSE(audio_input_listener_->devices_.empty());
+
InSequence s;
int index = 0;
@@ -225,6 +231,9 @@ TEST_F(AudioInputDeviceManagerTest, OpenNotExistingDevice) {
TEST_F(AudioInputDeviceManagerTest, OpenDeviceTwice) {
if (!CanRunAudioInputDeviceTests())
return;
+
+ ASSERT_FALSE(audio_input_listener_->devices_.empty());
+
InSequence s;
// Opens and closes the default device twice.
@@ -254,6 +263,9 @@ TEST_F(AudioInputDeviceManagerTest, OpenDeviceTwice) {
TEST_F(AudioInputDeviceManagerTest, StartAndStopSession) {
if (!CanRunAudioInputDeviceTests())
return;
+
+ ASSERT_FALSE(audio_input_listener_->devices_.empty());
+
InSequence s;
int index = 0;
@@ -297,6 +309,9 @@ TEST_F(AudioInputDeviceManagerTest, StartAndStopSession) {
TEST_F(AudioInputDeviceManagerTest, CloseWithoutStopSession) {
if (!CanRunAudioInputDeviceTests())
return;
+
+ ASSERT_FALSE(audio_input_listener_->devices_.empty());
+
InSequence s;
int index = 0;
@@ -343,6 +358,9 @@ TEST_F(AudioInputDeviceManagerTest, CloseWithoutStopSession) {
TEST_F(AudioInputDeviceManagerTest, StartDeviceTwice) {
if (!CanRunAudioInputDeviceTests())
return;
+
+ ASSERT_FALSE(audio_input_listener_->devices_.empty());
+
InSequence s;
// Create one EventHandler for each session.
diff --git a/content/browser/renderer_host/media/audio_input_renderer_host.cc b/content/browser/renderer_host/media/audio_input_renderer_host.cc
index 6a3e146..8d5131c 100644
--- a/content/browser/renderer_host/media/audio_input_renderer_host.cc
+++ b/content/browser/renderer_host/media/audio_input_renderer_host.cc
@@ -246,6 +246,7 @@ void AudioInputRendererHost::OnCreateStream(
// entry and construct an AudioInputController.
entry->writer.reset(writer.release());
entry->controller = media::AudioInputController::CreateLowLatency(
+ resource_context_->audio_manager(),
this,
audio_params,
device_id,
diff --git a/content/browser/renderer_host/media/audio_renderer_host.cc b/content/browser/renderer_host/media/audio_renderer_host.cc
index 2b2aa07..4d331b8 100644
--- a/content/browser/renderer_host/media/audio_renderer_host.cc
+++ b/content/browser/renderer_host/media/audio_renderer_host.cc
@@ -270,13 +270,15 @@ void AudioRendererHost::OnCreateStream(
// entry and construct an AudioOutputController.
entry->reader.reset(reader.release());
entry->controller =
- media::AudioOutputController::CreateLowLatency(this, audio_params,
- entry->reader.get());
+ media::AudioOutputController::CreateLowLatency(
+ resource_context_->audio_manager(), this, audio_params,
+ entry->reader.get());
} else {
// The choice of buffer capacity is based on experiment.
entry->controller =
- media::AudioOutputController::Create(this, audio_params,
- 3 * packet_size);
+ media::AudioOutputController::Create(
+ resource_context_->audio_manager(), this, audio_params,
+ 3 * packet_size);
}
if (!entry->controller) {
@@ -399,6 +401,8 @@ void AudioRendererHost::DeleteEntries() {
}
void AudioRendererHost::CloseAndDeleteStream(AudioEntry* entry) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
if (!entry->pending_close) {
entry->controller->Close(
base::Bind(&AudioRendererHost::OnStreamClosed, this, entry));
@@ -407,7 +411,8 @@ void AudioRendererHost::CloseAndDeleteStream(AudioEntry* entry) {
}
void AudioRendererHost::OnStreamClosed(AudioEntry* entry) {
- // Delete the entry after we've closed the stream.
+ // Delete the entry on the IO thread after we've closed the stream.
+ // (We're currently on the audio thread).
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&AudioRendererHost::DeleteEntry, this, entry));
diff --git a/content/browser/renderer_host/media/audio_renderer_host_unittest.cc b/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
index 4d62d35..715e19a5 100644
--- a/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
+++ b/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
@@ -42,7 +42,8 @@ static bool IsRunningHeadless() {
class MockAudioRendererHost : public AudioRendererHost {
public:
- MockAudioRendererHost(const content::ResourceContext* resource_context)
+ explicit MockAudioRendererHost(
+ const content::ResourceContext* resource_context)
: AudioRendererHost(resource_context),
shared_memory_length_(0) {
}
@@ -182,11 +183,12 @@ class AudioRendererHostTest : public testing::Test {
message_loop_.get()));
ui_thread_.reset(new BrowserThreadImpl(BrowserThread::UI,
message_loop_.get()));
-
+ audio_manager_ = AudioManager::Create();
observer_.reset(new MockMediaObserver());
content::MockResourceContext* context =
content::MockResourceContext::GetInstance();
context->set_media_observer(observer_.get());
+ context->set_audio_manager(audio_manager_);
host_ = new MockAudioRendererHost(context);
// Simulate IPC channel connected.
@@ -204,6 +206,14 @@ class AudioRendererHostTest : public testing::Test {
// We need to continue running message_loop_ to complete all destructions.
SyncWithAudioThread();
+ // Since the MockResourceContext object is a singleton that lives across
+ // multiple tests, we must clear pointers to objects that are about to die.
+ content::MockResourceContext* context =
+ content::MockResourceContext::GetInstance();
+ context->set_audio_manager(NULL);
+ context->set_media_observer(NULL);
+ audio_manager_ = NULL;
+
io_thread_.reset();
ui_thread_.reset();
}
@@ -338,9 +348,10 @@ class AudioRendererHostTest : public testing::Test {
}
// Called on the main thread.
- static void PostQuitOnAudioThread(MessageLoop* message_loop) {
- AudioManager::GetAudioManager()->GetMessageLoop()->PostTask(
- FROM_HERE, base::Bind(&PostQuitMessageLoop, message_loop));
+ static void PostQuitOnAudioThread(AudioManager* audio_manager,
+ MessageLoop* message_loop) {
+ audio_manager->GetMessageLoop()->PostTask(FROM_HERE,
+ base::Bind(&PostQuitMessageLoop, message_loop));
}
// SyncWithAudioThread() waits until all pending tasks on the audio thread
@@ -348,8 +359,12 @@ class AudioRendererHostTest : public testing::Test {
// current thread. It is used to synchronize with the audio thread when we are
// closing an audio stream.
void SyncWithAudioThread() {
+ // Don't use scoped_refptr to addref the AudioManager when posting
+ // to the thread that itself owns.
message_loop_->PostTask(
- FROM_HERE, base::Bind(&PostQuitOnAudioThread, message_loop_.get()));
+ FROM_HERE, base::Bind(&PostQuitOnAudioThread,
+ base::Unretained(audio_manager_.get()),
+ message_loop_.get()));
message_loop_->Run();
}
@@ -364,6 +379,7 @@ class AudioRendererHostTest : public testing::Test {
scoped_ptr<MessageLoop> message_loop_;
scoped_ptr<BrowserThreadImpl> io_thread_;
scoped_ptr<BrowserThreadImpl> ui_thread_;
+ scoped_refptr<AudioManager> audio_manager_;
DISALLOW_COPY_AND_ASSIGN(AudioRendererHostTest);
};
diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
index 1a11c90..0e3ba72 100644
--- a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
+++ b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
@@ -15,6 +15,7 @@
#include "content/common/media/media_stream_messages.h"
#include "content/common/media/media_stream_options.h"
#include "ipc/ipc_message_macros.h"
+#include "media/audio/audio_manager.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -151,9 +152,11 @@ class MediaStreamDispatcherHostTest : public testing::Test {
io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
message_loop_.get()));
+ audio_manager_ = AudioManager::Create();
+
// Create a MediaStreamManager instance and hand over pointer to
// ResourceContext.
- media_stream_manager_.reset(new MediaStreamManager());
+ media_stream_manager_.reset(new MediaStreamManager(audio_manager_));
// Make sure we use fake devices to avoid long delays.
media_stream_manager_->UseFakeDevice();
content::MockResourceContext::GetInstance()->set_media_stream_manager(
@@ -202,6 +205,7 @@ class MediaStreamDispatcherHostTest : public testing::Test {
scoped_ptr<BrowserThreadImpl> ui_thread_;
scoped_ptr<BrowserThreadImpl> io_thread_;
scoped_ptr<MediaStreamManager> media_stream_manager_;
+ scoped_refptr<AudioManager> audio_manager_;
};
TEST_F(MediaStreamDispatcherHostTest, GenerateStream) {
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc
index d9d8db2..6cb46b8 100644
--- a/content/browser/renderer_host/media/media_stream_manager.cc
+++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -16,6 +16,7 @@
#include "content/browser/renderer_host/media/video_capture_manager.h"
#include "content/common/media/media_stream_options.h"
#include "content/public/browser/browser_thread.h"
+#include "media/audio/audio_manager.h"
using content::BrowserThread;
@@ -80,10 +81,11 @@ struct MediaStreamManager::DeviceRequest {
StreamDeviceInfoArray video_devices;
};
-MediaStreamManager::MediaStreamManager()
+MediaStreamManager::MediaStreamManager(AudioManager* audio_manager)
: ALLOW_THIS_IN_INITIALIZER_LIST(
device_settings_(new MediaStreamDeviceSettings(this))),
- enumeration_in_progress_(kNumMediaStreamTypes, false) {
+ enumeration_in_progress_(kNumMediaStreamTypes, false),
+ audio_manager_(audio_manager) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
}
@@ -103,7 +105,8 @@ VideoCaptureManager* MediaStreamManager::video_capture_manager() {
AudioInputDeviceManager* MediaStreamManager::audio_input_device_manager() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (!audio_input_device_manager_.get()) {
- audio_input_device_manager_.reset(new AudioInputDeviceManager());
+ audio_input_device_manager_.reset(
+ new AudioInputDeviceManager(audio_manager_));
audio_input_device_manager_->Register(this);
}
return audio_input_device_manager_.get();
diff --git a/content/browser/renderer_host/media/media_stream_manager.h b/content/browser/renderer_host/media/media_stream_manager.h
index 0f48afe..1eb130e 100644
--- a/content/browser/renderer_host/media/media_stream_manager.h
+++ b/content/browser/renderer_host/media/media_stream_manager.h
@@ -25,11 +25,14 @@
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/ref_counted.h"
#include "content/browser/renderer_host/media/media_stream_provider.h"
#include "content/browser/renderer_host/media/media_stream_settings_requester.h"
#include "content/common/media/media_stream_options.h"
#include "content/common/content_export.h"
+class AudioManager;
+
namespace media_stream {
class AudioInputDeviceManager;
@@ -45,7 +48,7 @@ class CONTENT_EXPORT MediaStreamManager
: public MediaStreamProviderListener,
public SettingsRequester {
public:
- MediaStreamManager();
+ explicit MediaStreamManager(AudioManager* audio_manager);
virtual ~MediaStreamManager();
// Used to access VideoCaptureManager.
@@ -109,6 +112,7 @@ class CONTENT_EXPORT MediaStreamManager
// All non-closed request.
typedef std::map<std::string, DeviceRequest> DeviceRequests;
DeviceRequests requests_;
+ scoped_refptr<AudioManager> audio_manager_;
DISALLOW_COPY_AND_ASSIGN(MediaStreamManager);
};
diff --git a/content/browser/renderer_host/media/video_capture_host_unittest.cc b/content/browser/renderer_host/media/video_capture_host_unittest.cc
index da06442..cf99b49 100644
--- a/content/browser/renderer_host/media/video_capture_host_unittest.cc
+++ b/content/browser/renderer_host/media/video_capture_host_unittest.cc
@@ -19,6 +19,7 @@
#include "content/browser/renderer_host/media/video_capture_manager.h"
#include "content/browser/resource_context.h"
#include "content/common/media/video_capture_messages.h"
+#include "media/audio/audio_manager.h"
#include "media/video/capture/video_capture_types.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -205,9 +206,12 @@ class VideoCaptureHostTest : public testing::Test {
io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
message_loop_.get()));
+ audio_manager_ = AudioManager::Create();
+
// Create a MediaStreamManager instance and hand over pointer to
// ResourceContext.
- media_stream_manager_.reset(new media_stream::MediaStreamManager());
+ media_stream_manager_.reset(new media_stream::MediaStreamManager(
+ audio_manager_));
#ifndef TEST_REAL_CAPTURE_DEVICE
media_stream_manager_->UseFakeDevice();
@@ -368,6 +372,7 @@ class VideoCaptureHostTest : public testing::Test {
scoped_ptr<BrowserThreadImpl> ui_thread_;
scoped_ptr<BrowserThreadImpl> io_thread_;
scoped_ptr<media_stream::MediaStreamManager> media_stream_manager_;
+ scoped_refptr<AudioManager> audio_manager_;
DISALLOW_COPY_AND_ASSIGN(VideoCaptureHostTest);
};
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 1f9ff8d..61b136b 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -7,6 +7,10 @@
#include "content/browser/renderer_host/render_process_host_impl.h"
+#if defined(OS_WIN)
+#include <objbase.h> // For CoInitialize/CoUninitialize.
+#endif
+
#include <algorithm>
#include <limits>
#include <vector>
@@ -73,6 +77,7 @@
#include "content/browser/renderer_host/socket_stream_dispatcher_host.h"
#include "content/browser/renderer_host/text_input_client_message_filter.h"
#include "content/browser/resolve_proxy_msg_helper.h"
+#include "content/browser/resource_context.h"
#include "content/browser/speech/speech_input_dispatcher_host.h"
#include "content/browser/trace_message_filter.h"
#include "content/browser/user_metrics.h"
@@ -104,7 +109,6 @@
#include "webkit/plugins/plugin_switches.h"
#if defined(OS_WIN)
-#include <objbase.h>
#include "base/synchronization/waitable_event.h"
#include "content/common/font_cache_dispatcher_win.h"
#endif
@@ -460,55 +464,47 @@ void RenderProcessHostImpl::CreateMessageFilters() {
GetBrowserContext()->GetRequestContextForRenderProcess(GetID()),
widget_helper_));
channel_->AddFilter(render_message_filter);
+ content::BrowserContext* browser_context = GetBrowserContext();
+ const content::ResourceContext* resource_context =
+ &browser_context->GetResourceContext();
ResourceMessageFilter* resource_message_filter = new ResourceMessageFilter(
GetID(), content::PROCESS_TYPE_RENDERER,
- &GetBrowserContext()->GetResourceContext(),
- new RendererURLRequestContextSelector(GetBrowserContext(), GetID()),
+ resource_context,
+ new RendererURLRequestContextSelector(browser_context, GetID()),
content::GetContentClient()->browser()->GetResourceDispatcherHost());
channel_->AddFilter(resource_message_filter);
- channel_->AddFilter(new AudioInputRendererHost(
- &GetBrowserContext()->GetResourceContext()));
- channel_->AddFilter(
- new AudioRendererHost(&GetBrowserContext()->GetResourceContext()));
- channel_->AddFilter(
- new VideoCaptureHost(&GetBrowserContext()->GetResourceContext()));
- channel_->AddFilter(
- new AppCacheDispatcherHost(GetBrowserContext()->GetAppCacheService(),
- GetID()));
+ channel_->AddFilter(new AudioInputRendererHost(resource_context));
+ channel_->AddFilter(new AudioRendererHost(resource_context));
+ channel_->AddFilter(new VideoCaptureHost(resource_context));
+ channel_->AddFilter(new AppCacheDispatcherHost(
+ browser_context->GetAppCacheService(), GetID()));
channel_->AddFilter(new ClipboardMessageFilter());
- channel_->AddFilter(
- new DOMStorageMessageFilter(GetID(),
- GetBrowserContext()->GetWebKitContext()));
- channel_->AddFilter(
- new IndexedDBDispatcherHost(GetID(),
- GetBrowserContext()->GetWebKitContext()));
- channel_->AddFilter(
- GeolocationDispatcherHost::New(
- GetID(), GetBrowserContext()->GetGeolocationPermissionContext()));
+ channel_->AddFilter(new DOMStorageMessageFilter(GetID(),
+ browser_context->GetWebKitContext()));
+ channel_->AddFilter(new IndexedDBDispatcherHost(GetID(),
+ browser_context->GetWebKitContext()));
+ channel_->AddFilter(GeolocationDispatcherHost::New(
+ GetID(), browser_context->GetGeolocationPermissionContext()));
channel_->AddFilter(new GpuMessageFilter(GetID(), widget_helper_.get()));
channel_->AddFilter(new media_stream::MediaStreamDispatcherHost(
- &GetBrowserContext()->GetResourceContext(), GetID()));
- channel_->AddFilter(new PepperFileMessageFilter(GetID(),
- GetBrowserContext()));
- channel_->AddFilter(
- new PepperMessageFilter(&GetBrowserContext()->GetResourceContext()));
+ resource_context, GetID()));
+ channel_->AddFilter(new PepperFileMessageFilter(GetID(), browser_context));
+ channel_->AddFilter(new PepperMessageFilter(resource_context));
channel_->AddFilter(new speech_input::SpeechInputDispatcherHost(
- GetID(), GetBrowserContext()->GetRequestContext(),
- GetBrowserContext()->GetSpeechInputPreferences()));
- channel_->AddFilter(
- new FileSystemDispatcherHost(
- GetBrowserContext()->GetRequestContext(),
- GetBrowserContext()->GetFileSystemContext()));
+ GetID(), browser_context->GetRequestContext(),
+ browser_context->GetSpeechInputPreferences(), resource_context));
+ channel_->AddFilter(new FileSystemDispatcherHost(
+ browser_context->GetRequestContext(),
+ browser_context->GetFileSystemContext()));
channel_->AddFilter(new device_orientation::MessageFilter());
- channel_->AddFilter(
- new BlobMessageFilter(GetID(),
- GetBrowserContext()->GetBlobStorageContext()));
+ channel_->AddFilter(new BlobMessageFilter(GetID(),
+ browser_context->GetBlobStorageContext()));
channel_->AddFilter(new FileUtilitiesMessageFilter(GetID()));
channel_->AddFilter(new MimeRegistryMessageFilter());
channel_->AddFilter(new DatabaseMessageFilter(
- GetBrowserContext()->GetDatabaseTracker()));
+ browser_context->GetDatabaseTracker()));
#if defined(OS_MACOSX)
channel_->AddFilter(new TextInputClientMessageFilter(GetID()));
#elif defined(OS_WIN)
@@ -517,28 +513,24 @@ void RenderProcessHostImpl::CreateMessageFilters() {
SocketStreamDispatcherHost* socket_stream_dispatcher_host =
new SocketStreamDispatcherHost(
- new RendererURLRequestContextSelector(GetBrowserContext(), GetID()),
- &GetBrowserContext()->GetResourceContext());
+ new RendererURLRequestContextSelector(browser_context, GetID()),
+ resource_context);
channel_->AddFilter(socket_stream_dispatcher_host);
- channel_->AddFilter(
- new WorkerMessageFilter(
- GetID(),
- &GetBrowserContext()->GetResourceContext(),
- content::GetContentClient()->browser()->GetResourceDispatcherHost(),
- base::Bind(&RenderWidgetHelper::GetNextRoutingID,
- base::Unretained(widget_helper_.get()))));
+ channel_->AddFilter(new WorkerMessageFilter(GetID(), resource_context,
+ content::GetContentClient()->browser()->GetResourceDispatcherHost(),
+ base::Bind(&RenderWidgetHelper::GetNextRoutingID,
+ base::Unretained(widget_helper_.get()))));
#if defined(ENABLE_P2P_APIS)
- channel_->AddFilter(new content::P2PSocketDispatcherHost(
- &GetBrowserContext()->GetResourceContext()));
+ channel_->AddFilter(new content::P2PSocketDispatcherHost(resource_context));
#endif
channel_->AddFilter(new TraceMessageFilter());
channel_->AddFilter(new ResolveProxyMsgHelper(
- GetBrowserContext()->GetRequestContextForRenderProcess(GetID())));
- channel_->AddFilter(new QuotaDispatcherHost(
- GetID(), GetBrowserContext()->GetQuotaManager(),
+ browser_context->GetRequestContextForRenderProcess(GetID())));
+ channel_->AddFilter(new QuotaDispatcherHost(GetID(),
+ browser_context->GetQuotaManager(),
content::GetContentClient()->browser()->CreateQuotaPermissionContext()));
channel_->AddFilter(new content::GamepadBrowserMessageFilter(this));
channel_->AddFilter(new ProfilerMessageFilter());
diff --git a/content/browser/resource_context.cc b/content/browser/resource_context.cc
index d20b1e1..6eb7646 100644
--- a/content/browser/resource_context.cc
+++ b/content/browser/resource_context.cc
@@ -21,7 +21,9 @@ ResourceContext::ResourceContext()
quota_manager_(NULL),
host_zoom_map_(NULL),
media_observer_(NULL),
- media_stream_manager_(NULL) {
+ download_id_factory_(NULL),
+ media_stream_manager_(NULL),
+ audio_manager_(NULL) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}
@@ -158,6 +160,7 @@ DownloadIdFactory* ResourceContext::download_id_factory() const {
EnsureInitialized();
return download_id_factory_;
}
+
void ResourceContext::set_download_id_factory(
DownloadIdFactory* download_id_factory) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
@@ -177,4 +180,15 @@ void ResourceContext::set_media_stream_manager(
media_stream_manager_ = media_stream_manager;
}
+AudioManager* ResourceContext::audio_manager() const {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ EnsureInitialized();
+ return audio_manager_;
+}
+
+void ResourceContext::set_audio_manager(AudioManager* audio_manager) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ audio_manager_ = audio_manager;
+}
+
} // namespace content
diff --git a/content/browser/resource_context.h b/content/browser/resource_context.h
index 39358f5..21f36de 100644
--- a/content/browser/resource_context.h
+++ b/content/browser/resource_context.h
@@ -12,6 +12,7 @@
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
+class AudioManager;
class ChromeAppCacheService;
class ChromeBlobStorageContext;
class DownloadIdFactory;
@@ -83,6 +84,9 @@ class CONTENT_EXPORT ResourceContext {
void set_media_stream_manager(
media_stream::MediaStreamManager* media_stream_manager);
+ AudioManager* audio_manager() const;
+ void set_audio_manager(AudioManager* audio_manager);
+
protected:
ResourceContext();
@@ -100,6 +104,7 @@ class CONTENT_EXPORT ResourceContext {
MediaObserver* media_observer_;
DownloadIdFactory* download_id_factory_;
media_stream::MediaStreamManager* media_stream_manager_;
+ AudioManager* audio_manager_;
// Externally-defined data accessible by key.
typedef std::map<const void*, void*> UserDataMap;
diff --git a/content/browser/speech/speech_input_browsertest.cc b/content/browser/speech/speech_input_browsertest.cc
index 7dd1f9f..f0c6321 100644
--- a/content/browser/speech/speech_input_browsertest.cc
+++ b/content/browser/speech/speech_input_browsertest.cc
@@ -49,16 +49,13 @@ class FakeSpeechInputManager : public SpeechInputManager {
}
// SpeechInputManager methods.
- virtual void StartRecognition(Delegate* delegate,
- int caller_id,
- int render_process_id,
- int render_view_id,
- const gfx::Rect& element_rect,
- const std::string& language,
- const std::string& grammar,
- const std::string& origin_url,
- net::URLRequestContextGetter* context_getter,
- SpeechInputPreferences* speech_input_prefs) {
+ virtual void StartRecognition(Delegate* delegate, int caller_id,
+ int render_process_id, int render_view_id, const gfx::Rect& element_rect,
+ const std::string& language, const std::string& grammar,
+ const std::string& origin_url,
+ net::URLRequestContextGetter* context_getter,
+ SpeechInputPreferences* speech_input_prefs,
+ AudioManager* audio_manager) OVERRIDE {
VLOG(1) << "StartRecognition invoked.";
EXPECT_EQ(0, caller_id_);
EXPECT_EQ(NULL, delegate_);
@@ -77,18 +74,18 @@ class FakeSpeechInputManager : public SpeechInputManager {
base::Unretained(this)));
}
}
- virtual void CancelRecognition(int caller_id) {
+ virtual void CancelRecognition(int caller_id) OVERRIDE {
VLOG(1) << "CancelRecognition invoked.";
EXPECT_EQ(caller_id_, caller_id);
caller_id_ = 0;
delegate_ = NULL;
}
- virtual void StopRecording(int caller_id) {
+ virtual void StopRecording(int caller_id) OVERRIDE {
VLOG(1) << "StopRecording invoked.";
EXPECT_EQ(caller_id_, caller_id);
// Nothing to do here since we aren't really recording.
}
- virtual void CancelAllRequestsWithDelegate(Delegate* delegate) {
+ virtual void CancelAllRequestsWithDelegate(Delegate* delegate) OVERRIDE {
VLOG(1) << "CancelAllRequestsWithDelegate invoked.";
// delegate_ is set to NULL if a fake result was received (see below), so
// check that delegate_ matches the incoming parameter only when there is
@@ -98,23 +95,21 @@ class FakeSpeechInputManager : public SpeechInputManager {
}
protected:
- virtual void GetRequestInfo(bool* can_report_metrics,
- std::string* request_info) {}
- virtual void ShowRecognitionRequested(int caller_id,
- int render_process_id,
- int render_view_id,
- const gfx::Rect& element_rect) {}
- virtual void ShowWarmUp(int caller_id) {}
- virtual void ShowRecognizing(int caller_id) {}
- virtual void ShowRecording(int caller_id) {}
- virtual void ShowInputVolume(int caller_id,
- float volume,
- float noise_volume) {}
+ virtual void GetRequestInfo(AudioManager* audio_manager,
+ bool* can_report_metrics,
+ std::string* request_info) OVERRIDE {}
+ virtual void ShowRecognitionRequested(int caller_id, int render_process_id,
+ int render_view_id, const gfx::Rect& element_rect) OVERRIDE {}
+ virtual void ShowWarmUp(int caller_id) OVERRIDE {}
+ virtual void ShowRecognizing(int caller_id) OVERRIDE {}
+ virtual void ShowRecording(int caller_id) OVERRIDE {}
+ virtual void ShowInputVolume(int caller_id, float volume,
+ float noise_volume) OVERRIDE {}
virtual void ShowMicError(int caller_id,
- SpeechInputManager::MicError error) {}
+ SpeechInputManager::MicError error) OVERRIDE {}
virtual void ShowRecognizerError(int caller_id,
- content::SpeechInputError error) {}
- virtual void DoClose(int caller_id) {}
+ content::SpeechInputError error) OVERRIDE {}
+ virtual void DoClose(int caller_id) OVERRIDE {}
private:
void SetFakeRecognitionResult() {
diff --git a/content/browser/speech/speech_input_dispatcher_host.cc b/content/browser/speech/speech_input_dispatcher_host.cc
index 15b927b..8f4632c 100644
--- a/content/browser/speech/speech_input_dispatcher_host.cc
+++ b/content/browser/speech/speech_input_dispatcher_host.cc
@@ -5,6 +5,7 @@
#include "content/browser/speech/speech_input_dispatcher_host.h"
#include "base/lazy_instance.h"
+#include "content/browser/resource_context.h"
#include "content/browser/speech/speech_input_preferences.h"
#include "content/common/speech_input_messages.h"
#include "content/public/browser/content_browser_client.h"
@@ -114,11 +115,13 @@ void SpeechInputDispatcherHost::set_manager(SpeechInputManager* manager) {
SpeechInputDispatcherHost::SpeechInputDispatcherHost(
int render_process_id,
net::URLRequestContextGetter* context_getter,
- SpeechInputPreferences* speech_input_preferences)
+ SpeechInputPreferences* speech_input_preferences,
+ const content::ResourceContext* resource_context)
: render_process_id_(render_process_id),
may_have_pending_requests_(false),
context_getter_(context_getter),
- speech_input_preferences_(speech_input_preferences) {
+ speech_input_preferences_(speech_input_preferences),
+ resource_context_(resource_context) {
// This is initialized by Browser. Do not add any non-trivial
// initialization here, instead do it lazily when required (e.g. see the
// method |manager()|) or add an Init() method.
@@ -161,6 +164,7 @@ bool SpeechInputDispatcherHost::OnMessageReceived(
void SpeechInputDispatcherHost::OnStartRecognition(
const SpeechInputHostMsg_StartRecognition_Params &params) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
int caller_id = g_speech_input_callers.Get().CreateId(
render_process_id_, params.render_view_id, params.request_id);
manager()->StartRecognition(this, caller_id,
@@ -169,7 +173,8 @@ void SpeechInputDispatcherHost::OnStartRecognition(
params.language, params.grammar,
params.origin_url,
context_getter_.get(),
- speech_input_preferences_.get());
+ speech_input_preferences_.get(),
+ resource_context_->audio_manager());
}
void SpeechInputDispatcherHost::OnCancelRecognition(int render_view_id,
diff --git a/content/browser/speech/speech_input_dispatcher_host.h b/content/browser/speech/speech_input_dispatcher_host.h
index e6f91b1..a801ff0 100644
--- a/content/browser/speech/speech_input_dispatcher_host.h
+++ b/content/browser/speech/speech_input_dispatcher_host.h
@@ -13,6 +13,10 @@
struct SpeechInputHostMsg_StartRecognition_Params;
+namespace content {
+class ResourceContext;
+}
+
namespace speech_input {
// SpeechInputDispatcherHost is a delegate for Speech API messages used by
@@ -26,7 +30,8 @@ class SpeechInputDispatcherHost : public BrowserMessageFilter,
SpeechInputDispatcherHost(
int render_process_id,
net::URLRequestContextGetter* context_getter,
- SpeechInputPreferences* speech_input_preferences);
+ SpeechInputPreferences* speech_input_preferences,
+ const content::ResourceContext* resource_context);
// SpeechInputManager::Delegate methods.
virtual void SetRecognitionResult(
@@ -59,6 +64,7 @@ class SpeechInputDispatcherHost : public BrowserMessageFilter,
scoped_refptr<net::URLRequestContextGetter> context_getter_;
scoped_refptr<SpeechInputPreferences> speech_input_preferences_;
+ const content::ResourceContext* resource_context_;
static SpeechInputManager* manager_;
diff --git a/content/browser/speech/speech_input_manager.cc b/content/browser/speech/speech_input_manager.cc
index a3c243f..79a5753 100644
--- a/content/browser/speech/speech_input_manager.cc
+++ b/content/browser/speech/speech_input_manager.cc
@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "content/browser/renderer_host/render_view_host.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
+#include "content/browser/resource_context.h"
#include "content/browser/speech/speech_input_preferences.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/view_type.h"
@@ -26,7 +27,8 @@ struct SpeechInputManager::SpeechInputParams {
const std::string& grammar,
const std::string& origin_url,
net::URLRequestContextGetter* context_getter,
- SpeechInputPreferences* speech_input_prefs)
+ SpeechInputPreferences* speech_input_prefs,
+ AudioManager* audio_manager)
: delegate(delegate),
caller_id(caller_id),
render_process_id(render_process_id),
@@ -36,7 +38,8 @@ struct SpeechInputManager::SpeechInputParams {
grammar(grammar),
origin_url(origin_url),
context_getter(context_getter),
- speech_input_prefs(speech_input_prefs) {
+ speech_input_prefs(speech_input_prefs),
+ audio_manager_(audio_manager) {
}
Delegate* delegate;
@@ -49,6 +52,7 @@ struct SpeechInputManager::SpeechInputParams {
std::string origin_url;
net::URLRequestContextGetter* context_getter;
SpeechInputPreferences* speech_input_prefs;
+ scoped_refptr<AudioManager> audio_manager_;
};
SpeechInputManager::SpeechInputManager()
@@ -70,19 +74,34 @@ SpeechInputManagerDelegate* SpeechInputManager::GetDelegate(
return requests_.find(caller_id)->second.delegate;
}
-void SpeechInputManager::ShowAudioInputSettings() {
+// static
+void SpeechInputManager::ShowAudioInputSettings(AudioManager* audio_manager) {
// Since AudioManager::ShowAudioInputSettings can potentially launch external
// processes, do that in the FILE thread to not block the calling threads.
if (!BrowserThread::CurrentlyOn(BrowserThread::FILE)) {
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
- base::Bind(&SpeechInputManager::ShowAudioInputSettings));
+ base::Bind(&SpeechInputManager::ShowAudioInputSettings,
+ base::Unretained(audio_manager)));
return;
}
- DCHECK(AudioManager::GetAudioManager()->CanShowAudioInputSettings());
- if (AudioManager::GetAudioManager()->CanShowAudioInputSettings())
- AudioManager::GetAudioManager()->ShowAudioInputSettings();
+ DCHECK(audio_manager->CanShowAudioInputSettings());
+ if (audio_manager->CanShowAudioInputSettings())
+ audio_manager->ShowAudioInputSettings();
+}
+
+// static
+void SpeechInputManager::ShowAudioInputSettingsFromUI(
+ const content::ResourceContext* resource_context) {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&SpeechInputManager::ShowAudioInputSettingsFromUI,
+ base::Unretained(resource_context)));
+ return;
+ }
+ ShowAudioInputSettings(resource_context->audio_manager());
}
void SpeechInputManager::StartRecognition(
@@ -95,14 +114,15 @@ void SpeechInputManager::StartRecognition(
const std::string& grammar,
const std::string& origin_url,
net::URLRequestContextGetter* context_getter,
- SpeechInputPreferences* speech_input_prefs) {
+ SpeechInputPreferences* speech_input_prefs,
+ AudioManager* audio_manager) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&SpeechInputManager::CheckRenderViewTypeAndStartRecognition,
base::Unretained(this), SpeechInputParams(delegate, caller_id,
render_process_id, render_view_id, element_rect, language, grammar,
- origin_url, context_getter, speech_input_prefs)));
+ origin_url, context_getter, speech_input_prefs, audio_manager)));
}
void SpeechInputManager::CheckRenderViewTypeAndStartRecognition(
@@ -137,13 +157,15 @@ void SpeechInputManager::ProceedStartingRecognition(
ShowRecognitionRequested(
params.caller_id, params.render_process_id, params.render_view_id,
params.element_rect);
- GetRequestInfo(&can_report_metrics_, &request_info_);
+ GetRequestInfo(params.audio_manager_, &can_report_metrics_,
+ &request_info_);
SpeechInputRequest* request = &requests_[params.caller_id];
request->delegate = params.delegate;
request->recognizer = new SpeechRecognizer(
this, params.caller_id, params.language, params.grammar,
- params.context_getter, params.speech_input_prefs->filter_profanities(),
+ params.context_getter, params.audio_manager_,
+ params.speech_input_prefs->filter_profanities(),
request_info_, can_report_metrics_ ? params.origin_url : "");
request->is_active = false;
@@ -151,15 +173,20 @@ void SpeechInputManager::ProceedStartingRecognition(
}
void SpeechInputManager::StartRecognitionForRequest(int caller_id) {
- DCHECK(HasPendingRequest(caller_id));
+ SpeechRecognizerMap::iterator request = requests_.find(caller_id);
+ if (request == requests_.end()) {
+ NOTREACHED();
+ return;
+ }
// If we are currently recording audio for another caller, abort that cleanly.
if (recording_caller_id_)
CancelRecognitionAndInformDelegate(recording_caller_id_);
- if (!AudioManager::GetAudioManager()->HasAudioInputDevices()) {
+ AudioManager* audio_man = request->second.recognizer->audio_manager();
+ if (!audio_man->HasAudioInputDevices()) {
ShowMicError(caller_id, kNoDeviceAvailable);
- } else if (AudioManager::GetAudioManager()->IsRecordingInProcess()) {
+ } else if (audio_man->IsRecordingInProcess()) {
ShowMicError(caller_id, kDeviceInUse);
} else {
recording_caller_id_ = caller_id;
diff --git a/content/browser/speech/speech_input_manager.h b/content/browser/speech/speech_input_manager.h
index 65c381c..d78b0f9 100644
--- a/content/browser/speech/speech_input_manager.h
+++ b/content/browser/speech/speech_input_manager.h
@@ -16,6 +16,7 @@
class SpeechInputPreferences;
namespace content {
+class ResourceContext;
struct SpeechInputResult;
}
@@ -50,7 +51,13 @@ class CONTENT_EXPORT SpeechInputManager : public SpeechRecognizerDelegate {
// Invokes the platform provided microphone settings UI in a non-blocking way,
// via the BrowserThread::FILE thread.
- static void ShowAudioInputSettings();
+ static void ShowAudioInputSettings(AudioManager* audio_manager);
+
+ // Same as ShowAudioInputSettings above but can be called from the UI thread
+ // where the caller has a pointer to a resource context, but due to not
+ // running on the IO thread, cannot access its properties.
+ static void ShowAudioInputSettingsFromUI(
+ const content::ResourceContext* resource_context);
virtual ~SpeechInputManager();
@@ -71,7 +78,8 @@ class CONTENT_EXPORT SpeechInputManager : public SpeechRecognizerDelegate {
const std::string& grammar,
const std::string& origin_url,
net::URLRequestContextGetter* context_getter,
- SpeechInputPreferences* speech_input_prefs);
+ SpeechInputPreferences* speech_input_prefs,
+ AudioManager* audio_manager);
virtual void CancelRecognition(int caller_id);
virtual void CancelAllRequestsWithDelegate(Delegate* delegate);
virtual void StopRecording(int caller_id);
@@ -97,7 +105,8 @@ class CONTENT_EXPORT SpeechInputManager : public SpeechRecognizerDelegate {
// recognition and for fetching optional request information.
// Get the optional request information if available.
- virtual void GetRequestInfo(bool* can_report_metrics,
+ virtual void GetRequestInfo(AudioManager* audio_manager,
+ bool* can_report_metrics,
std::string* request_info) = 0;
// Called when recognition has been requested from point |element_rect_| on
diff --git a/content/browser/speech/speech_recognizer.cc b/content/browser/speech/speech_recognizer.cc
index a21bafb..4704867 100644
--- a/content/browser/speech/speech_recognizer.cc
+++ b/content/browser/speech/speech_recognizer.cc
@@ -61,6 +61,7 @@ SpeechRecognizer::SpeechRecognizer(Delegate* delegate,
const std::string& language,
const std::string& grammar,
net::URLRequestContextGetter* context_getter,
+ AudioManager* audio_manager,
bool filter_profanities,
const std::string& hardware_info,
const std::string& origin_url)
@@ -72,6 +73,7 @@ SpeechRecognizer::SpeechRecognizer(Delegate* delegate,
hardware_info_(hardware_info),
origin_url_(origin_url),
context_getter_(context_getter),
+ audio_manager_(audio_manager),
codec_(AudioEncoder::CODEC_FLAC),
encoder_(NULL),
endpointer_(kAudioSampleRate),
@@ -111,7 +113,8 @@ bool SpeechRecognizer::StartRecording() {
AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout,
kAudioSampleRate, kNumBitsPerAudioSample,
samples_per_packet);
- audio_controller_ = AudioInputController::Create(this, params);
+ audio_controller_ = AudioInputController::Create(audio_manager_, this,
+ params);
DCHECK(audio_controller_.get());
VLOG(1) << "SpeechRecognizer starting record.";
num_samples_recorded_ = 0;
@@ -215,7 +218,7 @@ void SpeechRecognizer::HandleOnData(string* data) {
bool speech_was_heard_before_packet = endpointer_.DidStartReceivingSpeech();
const short* samples = reinterpret_cast<const short*>(data->data());
- DCHECK((data->length() % sizeof(short)) == 0);
+ DCHECK_EQ((data->length() % sizeof(short)), 0U);
int num_samples = data->length() / sizeof(short);
encoder_->Encode(samples, num_samples);
float rms;
diff --git a/content/browser/speech/speech_recognizer.h b/content/browser/speech/speech_recognizer.h
index 5d64af7..f1b3cf2 100644
--- a/content/browser/speech/speech_recognizer.h
+++ b/content/browser/speech/speech_recognizer.h
@@ -86,6 +86,7 @@ class CONTENT_EXPORT SpeechRecognizer
const std::string& language,
const std::string& grammar,
net::URLRequestContextGetter* context_getter,
+ AudioManager* audio_manager,
bool filter_profanities,
const std::string& hardware_info,
const std::string& origin_url);
@@ -118,6 +119,8 @@ class CONTENT_EXPORT SpeechRecognizer
virtual void SetRecognitionResult(
const content::SpeechInputResult& result) OVERRIDE;
+ AudioManager* audio_manager() const { return audio_manager_; }
+
static const int kAudioSampleRate;
static const int kAudioPacketIntervalMs; // Duration of each audio packet.
static const ChannelLayout kChannelLayout;
@@ -145,6 +148,7 @@ class CONTENT_EXPORT SpeechRecognizer
scoped_ptr<SpeechRecognitionRequest> request_;
scoped_refptr<media::AudioInputController> audio_controller_;
scoped_refptr<net::URLRequestContextGetter> context_getter_;
+ scoped_refptr<AudioManager> audio_manager_;
AudioEncoder::Codec codec_;
scoped_ptr<AudioEncoder> encoder_;
Endpointer endpointer_;
diff --git a/content/browser/speech/speech_recognizer_unittest.cc b/content/browser/speech/speech_recognizer_unittest.cc
index 5845cd4..6dcaec6 100644
--- a/content/browser/speech/speech_recognizer_unittest.cc
+++ b/content/browser/speech/speech_recognizer_unittest.cc
@@ -7,6 +7,7 @@
#include "content/browser/browser_thread_impl.h"
#include "content/browser/speech/speech_recognizer.h"
#include "content/test/test_url_fetcher_factory.h"
+#include "media/audio/audio_manager.h"
#include "media/audio/test_audio_input_controller_factory.h"
#include "net/base/net_errors.h"
#include "net/url_request/url_request_status.h"
@@ -25,16 +26,16 @@ class SpeechRecognizerTest : public SpeechRecognizerDelegate,
public:
SpeechRecognizerTest()
: io_thread_(BrowserThread::IO, &message_loop_),
- ALLOW_THIS_IN_INITIALIZER_LIST(
- recognizer_(new SpeechRecognizer(this, 1, std::string(),
- std::string(), NULL, false,
- std::string(), std::string()))),
+ audio_manager_(AudioManager::Create()),
recording_complete_(false),
recognition_complete_(false),
result_received_(false),
audio_received_(false),
error_(content::SPEECH_INPUT_ERROR_NONE),
volume_(-1.0f) {
+ recognizer_ = new SpeechRecognizer(this, 1, std::string(), std::string(),
+ NULL, audio_manager_, false,
+ std::string(), std::string());
int audio_packet_length_bytes =
(SpeechRecognizer::kAudioSampleRate *
SpeechRecognizer::kAudioPacketIntervalMs *
@@ -111,6 +112,7 @@ class SpeechRecognizerTest : public SpeechRecognizerDelegate,
MessageLoopForIO message_loop_;
BrowserThreadImpl io_thread_;
scoped_refptr<SpeechRecognizer> recognizer_;
+ scoped_refptr<AudioManager> audio_manager_;
bool recording_complete_;
bool recognition_complete_;
bool result_received_;