summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-02-11 03:07:27 +0000
committerhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-02-11 03:07:27 +0000
commitf4d27d908bcf7db4efbac97318ecb5d52892823b (patch)
treef5b67f2318bdc653f9c948c4bc6454b574a4f1bd /chrome/browser
parentcccbe29c642c47816478b8ba3df9329fcee03728 (diff)
downloadchromium_src-f4d27d908bcf7db4efbac97318ecb5d52892823b.zip
chromium_src-f4d27d908bcf7db4efbac97318ecb5d52892823b.tar.gz
chromium_src-f4d27d908bcf7db4efbac97318ecb5d52892823b.tar.bz2
Construct AudioRendererHost in BrowserRendererProcessHost, also construct
ResourceMessageFilter with pointer to it so we can delegate requests to it from IPC later. Review URL: http://codereview.chromium.org/20131 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@9551 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/browser.scons3
-rw-r--r--chrome/browser/renderer_host/audio_renderer_host.cc57
-rw-r--r--chrome/browser/renderer_host/audio_renderer_host.h38
-rw-r--r--chrome/browser/renderer_host/audio_renderer_host_unittest.cc11
-rw-r--r--chrome/browser/renderer_host/browser_render_process_host.cc9
-rw-r--r--chrome/browser/renderer_host/browser_render_process_host.h4
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.cc5
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.h5
8 files changed, 114 insertions, 18 deletions
diff --git a/chrome/browser/browser.scons b/chrome/browser/browser.scons
index d1dcd6a..de44b18 100644
--- a/chrome/browser/browser.scons
+++ b/chrome/browser/browser.scons
@@ -15,6 +15,7 @@ env.SConscript([
'$ICU38_DIR/using_icu38.scons',
'$LIBPNG_DIR/using_libpng.scons',
'$LIBXML_DIR/using_libxml.scons',
+ '$MEDIA_DIR/using_media.scons',
'$NPAPI_DIR/using_npapi.scons',
'$SKIA_DIR/using_skia.scons',
'$ZLIB_DIR/using_zlib.scons',
@@ -508,6 +509,8 @@ input_files = ChromeFileList([
MSVSFilter('Renderer Host', [
'renderer_host/async_resource_handler.cc',
'renderer_host/async_resource_handler.h',
+ 'renderer_host/audio_renderer_host.cc',
+ 'renderer_host/audio_renderer_host.h',
'renderer_host/backing_store.h',
'renderer_host/backing_store.cc',
'renderer_host/backing_store_win.cc',
diff --git a/chrome/browser/renderer_host/audio_renderer_host.cc b/chrome/browser/renderer_host/audio_renderer_host.cc
index 66ee9ff..fd798ac 100644
--- a/chrome/browser/renderer_host/audio_renderer_host.cc
+++ b/chrome/browser/renderer_host/audio_renderer_host.cc
@@ -68,18 +68,21 @@ void AudioRendererHost::IPCAudioSource::NotifyPacketReady() {
AudioRendererHost::AudioRendererHost(MessageLoop* message_loop)
: next_id_(INVALID_ID+1),
- message_loop_(message_loop) {
+ io_loop_(message_loop) {
+ // Make sure we perform actual initialization operations in the thread where
+ // this object should live.
+ io_loop_->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &AudioRendererHost::OnInitialized));
}
AudioRendererHost::~AudioRendererHost() {
- DestroyAllStreams();
}
int AudioRendererHost::CreateStream(
IPC::Message::Sender* sender, base::ProcessHandle handle,
AudioManager::Format format, int channels, int sample_rate,
int bits_per_sample, size_t packet_size) {
- DCHECK(MessageLoop::current() == message_loop_);
+ DCHECK(MessageLoop::current() == io_loop_);
// Create the stream in the first place.
AudioOutputStream* stream = AudioManager::GetAudioManager()->MakeAudioStream(
@@ -100,7 +103,7 @@ int AudioRendererHost::CreateStream(
}
bool AudioRendererHost::Start(int stream_id) {
- DCHECK(MessageLoop::current() == message_loop_);
+ DCHECK(MessageLoop::current() == io_loop_);
IPCAudioSource* source = sources_.Lookup(stream_id);
if (source) {
source->stream()->Start(source);
@@ -110,7 +113,7 @@ bool AudioRendererHost::Start(int stream_id) {
}
bool AudioRendererHost::Stop(int stream_id) {
- DCHECK(MessageLoop::current() == message_loop_);
+ DCHECK(MessageLoop::current() == io_loop_);
IPCAudioSource* source = sources_.Lookup(stream_id);
if (source) {
source->stream()->Stop();
@@ -120,7 +123,7 @@ bool AudioRendererHost::Stop(int stream_id) {
}
bool AudioRendererHost::Close(int stream_id) {
- DCHECK(MessageLoop::current() == message_loop_);
+ DCHECK(MessageLoop::current() == io_loop_);
IPCAudioSource* source = sources_.Lookup(stream_id);
if (source) {
source->stream()->Close();
@@ -131,7 +134,7 @@ bool AudioRendererHost::Close(int stream_id) {
bool AudioRendererHost::SetVolume(
int stream_id, double left_channel, double right_channel) {
- DCHECK(MessageLoop::current() == message_loop_);
+ DCHECK(MessageLoop::current() == io_loop_);
IPCAudioSource* source = sources_.Lookup(stream_id);
if (source) {
source->stream()->SetVolume(left_channel, right_channel);
@@ -141,7 +144,7 @@ bool AudioRendererHost::SetVolume(
bool AudioRendererHost::GetVolume(
int stream_id, double* left_channel, double* right_channel) {
- DCHECK(MessageLoop::current() == message_loop_);
+ DCHECK(MessageLoop::current() == io_loop_);
IPCAudioSource* source = sources_.Lookup(stream_id);
if (source) {
source->stream()->GetVolume(left_channel, right_channel);
@@ -151,7 +154,7 @@ bool AudioRendererHost::GetVolume(
}
void AudioRendererHost::NotifyPacketReady(int stream_id) {
- DCHECK(MessageLoop::current() == message_loop_);
+ DCHECK(MessageLoop::current() == io_loop_);
IPCAudioSource* source = sources_.Lookup(stream_id);
if (source) {
source->NotifyPacketReady();
@@ -159,16 +162,48 @@ void AudioRendererHost::NotifyPacketReady(int stream_id) {
}
void AudioRendererHost::DestroyAllStreams() {
- DCHECK(MessageLoop::current() == message_loop_);
+ DCHECK(MessageLoop::current() == io_loop_);
// TODO(hclam): iterate on the map, close and delete every stream, and clear
// the map.
}
void AudioRendererHost::DestroySource(int stream_id) {
- DCHECK(MessageLoop::current() == message_loop_);
+ DCHECK(MessageLoop::current() == io_loop_);
IPCAudioSource* source = sources_.Lookup(stream_id);
if (source) {
sources_.Remove(stream_id);
delete source;
}
}
+
+void AudioRendererHost::Destroy() {
+ // Post a message to the thread where this object should live and do the
+ // actual operations there.
+ io_loop_->PostTask(
+ FROM_HERE, NewRunnableMethod(this, &AudioRendererHost::OnDestroyed));
+}
+
+void AudioRendererHost::OnInitialized() {
+ DCHECK(MessageLoop::current() == io_loop_);
+
+ // Increase the ref count of this object so it is active until we do
+ // Release().
+ AddRef();
+
+ // Also create the AudioManager singleton in this thread.
+ // TODO(hclam): figure out a better location to initialize the AudioManager
+ // singleton.
+ AudioManager::GetAudioManager();
+}
+
+void AudioRendererHost::OnDestroyed() {
+ DCHECK(MessageLoop::current() == io_loop_);
+
+ // Destroy audio streams only in the thread it should happen.
+ // TODO(hclam): make sure we don't call IPC::Message::Sender inside
+ // IPCAudioSource because it is most likely be destroyed.
+ DestroyAllStreams();
+
+ // Decrease the reference to this object, which may lead to self-destruction.
+ Release();
+}
diff --git a/chrome/browser/renderer_host/audio_renderer_host.h b/chrome/browser/renderer_host/audio_renderer_host.h
index 4df24ba..8128d61 100644
--- a/chrome/browser/renderer_host/audio_renderer_host.h
+++ b/chrome/browser/renderer_host/audio_renderer_host.h
@@ -17,11 +17,31 @@
// passing a SharedMemoryHandle for filling the buffer.
// NotifyPacketReady(|stream_id|) would be called when the buffer is filled
// and ready to be consumed.
+//
+// This class is owned by BrowserRenderProcessHost, and instantiated on UI
+// thread, but all other operations and method calls (except Destroy()) happens
+// in IO thread, so we need to be extra careful about the lifetime of this
+// object. AudioManager is a singleton and created in IO thread, audio output
+// streams are also created in the IO thread, so we need to destroy them also
+// in IO thread. After this class is created, a task of OnInitialized() is
+// posted on IO thread in which singleton of AudioManager is created and
+// AddRef() is called to increase one ref count of this object. Owner of this
+// class should call Destroy() before decrementing the ref count to this object,
+// which essentially post a task of OnDestroyed() on IO thread. Inside
+// OnDestroyed(), audio output streams are destroyed and Release() is called
+// which may result in self-destruction.
+//
+// TODO(hclam): Have these things done before having real implementations:
+// 1. Make sure this class has greater or equal lifetime to
+// IPC:Message::Sender, essentially ResourceMessageFilter.
+// 2. Listen to destruction event of the browser and do cleanup in case this
+// class is not destructed nicely during browser close.
#ifndef CHROME_BROWSER_RENDERER_HOST_AUDIO_RENDERER_HOST_H_
#define CHROME_BROWSER_RENDERER_HOST_AUDIO_RENDERER_HOST_H_
#include "base/id_map.h"
+#include "base/ref_counted.h"
#include "base/shared_memory.h"
#include "chrome/common/ipc_message.h"
#include "media/audio/audio_output.h"
@@ -29,7 +49,7 @@
class AudioManager;
class MessageLoop;
-class AudioRendererHost {
+class AudioRendererHost : public base::RefCountedThreadSafe<AudioRendererHost> {
public:
static const int32 INVALID_ID = 0;
@@ -74,14 +94,24 @@ class AudioRendererHost {
// consumed.
void NotifyPacketReady(int32 stream_id);
- // Destroy all audio output streams.
- void DestroyAllStreams();
+ // Called from UI thread from the owner of this object.
+ void Destroy();
// Destroy the stream specified by |stream_id| and remove it from map.
// *DO NOT* call this method other than from IPCAudioSource.
void DestroySource(int32 stream_id);
private:
+ // Methods called on IO thread.
+ // Called on IO thread when this object is created and initialized.
+ void OnInitialized();
+ // Called on IO thread when this object needs to be destroyed and after
+ // Destroy() is called from owner of this class in UI thread.
+ void OnDestroyed();
+
+ // Destroy all audio output streams.
+ void DestroyAllStreams();
+
// The container for AudioOutputStream and serves audio packet for it by IPC.
class IPCAudioSource : public AudioOutputStream::AudioSourceCallback {
public:
@@ -124,7 +154,7 @@ class AudioRendererHost {
// Only used for DCHECKs to make sure all methods calls are from the same
// thread as this object is created.
- MessageLoop* message_loop_;
+ MessageLoop* io_loop_;
DISALLOW_COPY_AND_ASSIGN(AudioRendererHost);
};
diff --git a/chrome/browser/renderer_host/audio_renderer_host_unittest.cc b/chrome/browser/renderer_host/audio_renderer_host_unittest.cc
index 443966b..d7ab831 100644
--- a/chrome/browser/renderer_host/audio_renderer_host_unittest.cc
+++ b/chrome/browser/renderer_host/audio_renderer_host_unittest.cc
@@ -11,10 +11,17 @@
class AudioRendererHostTest : public testing::Test {
protected:
virtual void SetUp() {
- host_.reset(new AudioRendererHost(MessageLoop::current()));
+ // Create a message loop so AudioRendererHost can use it.
+ message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO));
+ host_ = new AudioRendererHost(MessageLoop::current());
}
- scoped_ptr<AudioRendererHost> host_;
+ virtual void TearDown() {
+ host_->Destroy();
+ }
+
+ scoped_refptr<AudioRendererHost> host_;
+ scoped_ptr<MessageLoop> message_loop_;
};
TEST_F(AudioRendererHostTest, NoTest) {
diff --git a/chrome/browser/renderer_host/browser_render_process_host.cc b/chrome/browser/renderer_host/browser_render_process_host.cc
index b020feb..24d5f4d 100644
--- a/chrome/browser/renderer_host/browser_render_process_host.cc
+++ b/chrome/browser/renderer_host/browser_render_process_host.cc
@@ -155,6 +155,10 @@ BrowserRenderProcessHost::~BrowserRenderProcessHost() {
// We may have some unsent messages at this point, but that's OK.
channel_.reset();
+ // Destroy the AudioRendererHost properly.
+ if (audio_renderer_host_.get())
+ audio_renderer_host_->Destroy();
+
if (process_.handle() && !run_renderer_in_process()) {
ProcessWatcher::EnsureProcessTerminated(process_.handle());
}
@@ -195,8 +199,13 @@ bool BrowserRenderProcessHost::Init() {
// run the IPC channel on the shared IO thread.
base::Thread* io_thread = g_browser_process->io_thread();
+ // Construct the AudioRendererHost with the IO thread.
+ audio_renderer_host_ =
+ new AudioRendererHost(io_thread->message_loop());
+
scoped_refptr<ResourceMessageFilter> resource_message_filter =
new ResourceMessageFilter(g_browser_process->resource_dispatcher_host(),
+ audio_renderer_host_.get(),
PluginService::GetInstance(),
g_browser_process->print_job_manager(),
host_id(),
diff --git a/chrome/browser/renderer_host/browser_render_process_host.h b/chrome/browser/renderer_host/browser_render_process_host.h
index 3e40d50..d089516 100644
--- a/chrome/browser/renderer_host/browser_render_process_host.h
+++ b/chrome/browser/renderer_host/browser_render_process_host.h
@@ -13,6 +13,7 @@
#include "base/ref_counted.h"
#include "base/scoped_ptr.h"
#include "base/shared_memory.h"
+#include "chrome/browser/renderer_host/audio_renderer_host.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/common/notification_observer.h"
#include "webkit/glue/cache_manager.h"
@@ -136,6 +137,9 @@ class BrowserRenderProcessHost : public RenderProcessHost,
// IO thread.
scoped_refptr<RenderWidgetHelper> widget_helper_;
+ // The host of audio renderers in the renderer process.
+ scoped_refptr<AudioRendererHost> audio_renderer_host_;
+
DISALLOW_COPY_AND_ASSIGN(BrowserRenderProcessHost);
};
diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc
index 2db7124..19f0ad9 100644
--- a/chrome/browser/renderer_host/resource_message_filter.cc
+++ b/chrome/browser/renderer_host/resource_message_filter.cc
@@ -13,6 +13,7 @@
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/net/dns_global.h"
#include "chrome/browser/profile.h"
+#include "chrome/browser/renderer_host/audio_renderer_host.h"
#include "chrome/browser/renderer_host/browser_render_process_host.h"
#include "chrome/browser/renderer_host/render_widget_helper.h"
#include "chrome/common/chrome_plugin_lib.h"
@@ -92,6 +93,7 @@ class WriteClipboardTask : public Task {
ResourceMessageFilter::ResourceMessageFilter(
ResourceDispatcherHost* resource_dispatcher_host,
+ AudioRendererHost* audio_renderer_host,
PluginService* plugin_service,
printing::PrintJobManager* print_job_manager,
int render_process_host_id,
@@ -108,7 +110,8 @@ ResourceMessageFilter::ResourceMessageFilter(
render_handle_(NULL),
request_context_(profile->GetRequestContext()),
profile_(profile),
- render_widget_helper_(render_widget_helper) {
+ render_widget_helper_(render_widget_helper),
+ audio_renderer_host_(audio_renderer_host) {
DCHECK(request_context_.get());
DCHECK(request_context_->cookie_store());
diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h
index c4d75e3..34d3c3d 100644
--- a/chrome/browser/renderer_host/resource_message_filter.h
+++ b/chrome/browser/renderer_host/resource_message_filter.h
@@ -25,6 +25,7 @@
#include "chrome/common/temp_scaffolding_stubs.h"
#endif
+class AudioRendererHost;
class ClipboardService;
class Profile;
class RenderWidgetHelper;
@@ -57,6 +58,7 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
// ResourceMessageFilter is 'given' ownership of the spellchecker
// object and must clean it up on exit.
ResourceMessageFilter(ResourceDispatcherHost* resource_dispatcher_host,
+ AudioRendererHost* audio_renderer_host,
PluginService* plugin_service,
printing::PrintJobManager* print_job_manager,
int render_process_host_id,
@@ -239,6 +241,9 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
scoped_refptr<RenderWidgetHelper> render_widget_helper_;
+ // Object that should take care of audio related resource requests.
+ scoped_refptr<AudioRendererHost> audio_renderer_host_;
+
DISALLOW_COPY_AND_ASSIGN(ResourceMessageFilter);
};