diff options
author | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-16 22:30:19 +0000 |
---|---|---|
committer | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-16 22:30:19 +0000 |
commit | 230b7efa5edf3fe5964b55ea0aa801563996d4fc (patch) | |
tree | 4ee6e0ffbbb5ca3bc5699e3adefa390279c6f357 /content | |
parent | eb7d6dd92533eae8c2514735750ccd8d0e9c5875 (diff) | |
download | chromium_src-230b7efa5edf3fe5964b55ea0aa801563996d4fc.zip chromium_src-230b7efa5edf3fe5964b55ea0aa801563996d4fc.tar.gz chromium_src-230b7efa5edf3fe5964b55ea0aa801563996d4fc.tar.bz2 |
Move a bunch of html5 renderer code to content.
TBR=avi
Review URL: http://codereview.chromium.org/6703003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@78449 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
20 files changed, 2177 insertions, 2 deletions
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi index dfd5246..cfed384 100644 --- a/content/content_renderer.gypi +++ b/content/content_renderer.gypi @@ -18,14 +18,28 @@ '..', ], 'sources': [ + 'renderer/audio_device.cc', + 'renderer/audio_device.h', + 'renderer/audio_message_filter.cc', + 'renderer/audio_message_filter.h', + 'renderer/cookie_message_filter.cc', + 'renderer/cookie_message_filter.h', + 'renderer/device_orientation_dispatcher.cc', + 'renderer/device_orientation_dispatcher.h', + 'renderer/geolocation_dispatcher.cc', + 'renderer/geolocation_dispatcher.h', 'renderer/ggl.cc', 'renderer/ggl.h', + 'renderer/indexed_db_dispatcher.cc', + 'renderer/indexed_db_dispatcher.h', 'renderer/media/audio_renderer_impl.cc', 'renderer/media/audio_renderer_impl.h', 'renderer/media/gles2_video_decode_context.cc', 'renderer/media/gles2_video_decode_context.h', 'renderer/media/ipc_video_decoder.cc', 'renderer/media/ipc_video_decoder.h', + 'renderer/notification_provider.cc', + 'renderer/notification_provider.h', 'renderer/p2p/ipc_network_manager.cc', 'renderer/p2p/ipc_network_manager.h', 'renderer/p2p/ipc_socket_factory.cc', @@ -34,6 +48,8 @@ 'renderer/p2p/socket_client.h', 'renderer/p2p/socket_dispatcher.cc', 'renderer/p2p/socket_dispatcher.h', + 'renderer/speech_input_dispatcher.cc', + 'renderer/speech_input_dispatcher.h', ], }, ], diff --git a/content/renderer/audio_device.cc b/content/renderer/audio_device.cc new file mode 100644 index 0000000..cf1dd7d --- /dev/null +++ b/content/renderer/audio_device.cc @@ -0,0 +1,188 @@ +// Copyright (c) 2010 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/renderer/audio_device.h" + +#include "base/singleton.h" +#include "chrome/common/render_messages.h" +#include "chrome/common/render_messages_params.h" +#include "chrome/renderer/render_thread.h" +#include "media/audio/audio_util.h" + +scoped_refptr<AudioMessageFilter> AudioDevice::filter_; + +namespace { + +// AudioMessageFilterCreator is intended to be used as a singleton so we can +// get access to a shared AudioMessageFilter. +// Example usage: +// AudioMessageFilter* filter = AudioMessageFilterCreator::SharedFilter(); + +class AudioMessageFilterCreator { + public: + AudioMessageFilterCreator() { + int routing_id; + RenderThread::current()->Send( + new ViewHostMsg_GenerateRoutingID(&routing_id)); + filter_ = new AudioMessageFilter(routing_id); + RenderThread::current()->AddFilter(filter_); + } + + static AudioMessageFilter* SharedFilter() { + return GetInstance()->filter_.get(); + } + + static AudioMessageFilterCreator* GetInstance() { + return Singleton<AudioMessageFilterCreator>::get(); + } + + private: + scoped_refptr<AudioMessageFilter> filter_; +}; + +} + +AudioDevice::AudioDevice(size_t buffer_size, + int channels, + double sample_rate, + RenderCallback* callback) + : buffer_size_(buffer_size), + channels_(channels), + sample_rate_(sample_rate), + callback_(callback), + stream_id_(0) { + audio_data_.reserve(channels); + for (int i = 0; i < channels; ++i) { + float* channel_data = new float[buffer_size]; + audio_data_.push_back(channel_data); + } +} + +AudioDevice::~AudioDevice() { + Stop(); + for (int i = 0; i < channels_; ++i) + delete [] audio_data_[i]; +} + +bool AudioDevice::Start() { + // Make sure we don't call Start() more than once. + DCHECK_EQ(0, stream_id_); + if (stream_id_) + return false; + + // Lazily create the message filter and share across AudioDevice instances. + filter_ = AudioMessageFilterCreator::SharedFilter(); + + stream_id_ = filter_->AddDelegate(this); + + ViewHostMsg_Audio_CreateStream_Params params; + params.params.format = AudioParameters::AUDIO_PCM_LOW_LATENCY; + params.params.channels = channels_; + params.params.sample_rate = static_cast<int>(sample_rate_); + params.params.bits_per_sample = 16; + params.params.samples_per_packet = buffer_size_; + + filter_->Send( + new ViewHostMsg_CreateAudioStream(0, stream_id_, params, true)); + + return true; +} + +bool AudioDevice::Stop() { + if (stream_id_) { + OnDestroy(); + return true; + } + return false; +} + +void AudioDevice::OnDestroy() { + // Make sure we don't call destroy more than once. + DCHECK_NE(0, stream_id_); + if (!stream_id_) + return; + + filter_->RemoveDelegate(stream_id_); + filter_->Send(new ViewHostMsg_CloseAudioStream(0, stream_id_)); + stream_id_ = 0; + if (audio_thread_.get()) { + socket_->Close(); + audio_thread_->Join(); + } +} + +void AudioDevice::OnRequestPacket(AudioBuffersState buffers_state) { + // This method does not apply to the low-latency system. + NOTIMPLEMENTED(); +} + +void AudioDevice::OnStateChanged( + const ViewMsg_AudioStreamState_Params& state) { + // Not needed in this simple implementation. + NOTIMPLEMENTED(); +} + +void AudioDevice::OnCreated( + base::SharedMemoryHandle handle, uint32 length) { + // Not needed in this simple implementation. + NOTIMPLEMENTED(); +} + +void AudioDevice::OnLowLatencyCreated( + base::SharedMemoryHandle handle, + base::SyncSocket::Handle socket_handle, + uint32 length) { + +#if defined(OS_WIN) + DCHECK(handle); + DCHECK(socket_handle); +#else + DCHECK_GE(handle.fd, 0); + DCHECK_GE(socket_handle, 0); +#endif + DCHECK(length); + DCHECK(!audio_thread_.get()); + + // TODO(crogers) : check that length is big enough for buffer_size_ + + shared_memory_.reset(new base::SharedMemory(handle, false)); + shared_memory_->Map(length); + + socket_.reset(new base::SyncSocket(socket_handle)); + // Allow the client to pre-populate the buffer. + FireRenderCallback(); + + // TODO(crogers): we could optionally set the thread to high-priority + audio_thread_.reset( + new base::DelegateSimpleThread(this, "renderer_audio_thread")); + audio_thread_->Start(); + + filter_->Send(new ViewHostMsg_PlayAudioStream(0, stream_id_)); +} + +void AudioDevice::OnVolume(double volume) { + // Not needed in this simple implementation. + NOTIMPLEMENTED(); +} + +// Our audio thread runs here. +void AudioDevice::Run() { + int pending_data; + while (sizeof(pending_data) == socket_->Receive(&pending_data, + sizeof(pending_data)) && + pending_data >= 0) { + FireRenderCallback(); + } +} + +void AudioDevice::FireRenderCallback() { + if (callback_) { + // Ask client to render audio. + callback_->Render(audio_data_, buffer_size_); + + // Interleave, scale, and clip to int16. + int16* output_buffer16 = static_cast<int16*>(shared_memory_data()); + media::InterleaveFloatToInt16(audio_data_, output_buffer16, buffer_size_); + } +} diff --git a/content/renderer/audio_device.h b/content/renderer/audio_device.h new file mode 100644 index 0000000..9f152bf --- /dev/null +++ b/content/renderer/audio_device.h @@ -0,0 +1,84 @@ +// Copyright (c) 2010 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_RENDERER_AUDIO_DEVICE_H_ +#define CONTENT_RENDERER_AUDIO_DEVICE_H_ +#pragma once + +#include <vector> + +#include "base/basictypes.h" +#include "base/scoped_ptr.h" +#include "base/shared_memory.h" +#include "base/threading/simple_thread.h" +#include "content/renderer/audio_message_filter.h" + +// Each instance of AudioDevice corresponds to one host stream. +// This class is not thread-safe, so its methods must be called from +// the same thread. +class AudioDevice : public AudioMessageFilter::Delegate, + public base::DelegateSimpleThread::Delegate { + public: + class RenderCallback { + public: + virtual void Render(const std::vector<float*>& audio_data, + size_t number_of_frames) = 0; + protected: + virtual ~RenderCallback() {} + }; + + // |buffer_size| is the number of sample-frames. + AudioDevice(size_t buffer_size, + int channels, + double sample_rate, + RenderCallback* callback); + virtual ~AudioDevice(); + + // Returns |true| on success. + bool Start(); + bool Stop(); + + private: + // AudioMessageFilter::Delegate implementation. + virtual void OnRequestPacket(AudioBuffersState buffers_state); + virtual void OnStateChanged(const ViewMsg_AudioStreamState_Params& state); + virtual void OnCreated(base::SharedMemoryHandle handle, uint32 length); + virtual void OnLowLatencyCreated(base::SharedMemoryHandle handle, + base::SyncSocket::Handle socket_handle, + uint32 length); + virtual void OnVolume(double volume); + virtual void OnDestroy(); + + // DelegateSimpleThread::Delegate implementation. + virtual void Run(); + + // Format + size_t buffer_size_; // in sample-frames + int channels_; + double sample_rate_; + + // Calls the client's callback for rendering audio. + void FireRenderCallback(); + RenderCallback* callback_; + + // The client callback renders audio into here. + std::vector<float*> audio_data_; + + // Callbacks for rendering audio occur on this thread. + scoped_ptr<base::DelegateSimpleThread> audio_thread_; + + // IPC message stuff. + base::SharedMemory* shared_memory() { return shared_memory_.get(); } + base::SyncSocket* socket() { return socket_.get(); } + void* shared_memory_data() { return shared_memory()->memory(); } + + static scoped_refptr<AudioMessageFilter> filter_; + int32 stream_id_; + scoped_ptr<base::SharedMemory> shared_memory_; + scoped_ptr<base::SyncSocket> socket_; + + DISALLOW_COPY_AND_ASSIGN(AudioDevice); +}; + +#endif // CONTENT_RENDERER_AUDIO_DEVICE_H_ diff --git a/content/renderer/audio_message_filter.cc b/content/renderer/audio_message_filter.cc new file mode 100644 index 0000000..317943c --- /dev/null +++ b/content/renderer/audio_message_filter.cc @@ -0,0 +1,147 @@ +// Copyright (c) 2010 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/renderer/audio_message_filter.h" + +#include "base/message_loop.h" +#include "base/time.h" +#include "chrome/common/render_messages.h" +#include "chrome/common/render_messages_params.h" +#include "ipc/ipc_logging.h" + +AudioMessageFilter::AudioMessageFilter(int32 route_id) + : channel_(NULL), + route_id_(route_id), + message_loop_(NULL) { +} + +AudioMessageFilter::~AudioMessageFilter() { +} + +// Called on the IPC thread. +bool AudioMessageFilter::Send(IPC::Message* message) { + if (!channel_) { + delete message; + return false; + } + + if (MessageLoop::current() != message_loop_) { + // Can only access the IPC::Channel on the IPC thread since it's not thread + // safe. + message_loop_->PostTask( + FROM_HERE, NewRunnableMethod(this, &AudioMessageFilter::Send, message)); + return true; + } + + message->set_routing_id(route_id_); + return channel_->Send(message); +} + +bool AudioMessageFilter::OnMessageReceived(const IPC::Message& message) { + if (message.routing_id() != route_id_) + return false; + + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(AudioMessageFilter, message) + IPC_MESSAGE_HANDLER(ViewMsg_RequestAudioPacket, OnRequestPacket) + IPC_MESSAGE_HANDLER(ViewMsg_NotifyAudioStreamCreated, OnStreamCreated) + IPC_MESSAGE_HANDLER(ViewMsg_NotifyLowLatencyAudioStreamCreated, + OnLowLatencyStreamCreated) + IPC_MESSAGE_HANDLER(ViewMsg_NotifyAudioStreamStateChanged, + OnStreamStateChanged) + IPC_MESSAGE_HANDLER(ViewMsg_NotifyAudioStreamVolume, OnStreamVolume) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +void AudioMessageFilter::OnFilterAdded(IPC::Channel* channel) { + // Captures the message loop for IPC. + message_loop_ = MessageLoop::current(); + channel_ = channel; +} + +void AudioMessageFilter::OnFilterRemoved() { + channel_ = NULL; +} + +void AudioMessageFilter::OnChannelClosing() { + channel_ = NULL; +} + +void AudioMessageFilter::OnRequestPacket(const IPC::Message& msg, + int stream_id, + AudioBuffersState buffers_state) { + Delegate* delegate = delegates_.Lookup(stream_id); + if (!delegate) { + DLOG(WARNING) << "Got audio packet request for a non-existent or removed" + " audio renderer."; + return; + } + + delegate->OnRequestPacket(buffers_state); +} + +void AudioMessageFilter::OnStreamCreated(int stream_id, + base::SharedMemoryHandle handle, + uint32 length) { + Delegate* delegate = delegates_.Lookup(stream_id); + if (!delegate) { + DLOG(WARNING) << "Got audio stream event for a non-existent or removed" + " audio renderer."; + return; + } + delegate->OnCreated(handle, length); +} + +void AudioMessageFilter::OnLowLatencyStreamCreated( + int stream_id, + base::SharedMemoryHandle handle, +#if defined(OS_WIN) + base::SyncSocket::Handle socket_handle, +#else + base::FileDescriptor socket_descriptor, +#endif + uint32 length) { + Delegate* delegate = delegates_.Lookup(stream_id); + if (!delegate) { + DLOG(WARNING) << "Got audio stream event for a non-existent or removed" + " audio renderer."; + return; + } +#if !defined(OS_WIN) + base::SyncSocket::Handle socket_handle = socket_descriptor.fd; +#endif + delegate->OnLowLatencyCreated(handle, socket_handle, length); +} + +void AudioMessageFilter::OnStreamStateChanged( + int stream_id, + const ViewMsg_AudioStreamState_Params& state) { + Delegate* delegate = delegates_.Lookup(stream_id); + if (!delegate) { + DLOG(WARNING) << "Got audio stream event for a non-existent or removed" + " audio renderer."; + return; + } + delegate->OnStateChanged(state); +} + +void AudioMessageFilter::OnStreamVolume(int stream_id, double volume) { + Delegate* delegate = delegates_.Lookup(stream_id); + if (!delegate) { + DLOG(WARNING) << "Got audio stream event for a non-existent or removed" + " audio renderer."; + return; + } + delegate->OnVolume(volume); +} + +int32 AudioMessageFilter::AddDelegate(Delegate* delegate) { + return delegates_.Add(delegate); +} + +void AudioMessageFilter::RemoveDelegate(int32 id) { + delegates_.Remove(id); +} diff --git a/content/renderer/audio_message_filter.h b/content/renderer/audio_message_filter.h new file mode 100644 index 0000000..e362839 --- /dev/null +++ b/content/renderer/audio_message_filter.h @@ -0,0 +1,121 @@ +// Copyright (c) 2010 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. +// +// MessageFilter that handles audio messages and delegates them to audio +// renderers. Created on render thread, AudioMessageFilter is operated on +// IO thread (main thread of render process), it intercepts audio messages +// and process them on IO thread since these messages are time critical. + +#ifndef CONTENT_RENDERER_AUDIO_MESSAGE_FILTER_H_ +#define CONTENT_RENDERER_AUDIO_MESSAGE_FILTER_H_ +#pragma once + +#include "base/gtest_prod_util.h" +#include "base/id_map.h" +#include "base/shared_memory.h" +#include "base/sync_socket.h" +#include "ipc/ipc_channel_proxy.h" +#include "media/audio/audio_buffers_state.h" + +struct ViewMsg_AudioStreamState_Params; + +namespace base { +class Time; +} + +class AudioMessageFilter : public IPC::ChannelProxy::MessageFilter { + public: + class Delegate { + public: + // Called when an audio packet is requested from the browser process. + virtual void OnRequestPacket(AudioBuffersState buffers_state) = 0; + + // Called when state of an audio stream has changed in the browser process. + virtual void OnStateChanged( + const ViewMsg_AudioStreamState_Params& state) = 0; + + // Called when an audio stream has been created in the browser process. + virtual void OnCreated(base::SharedMemoryHandle handle, uint32 length) = 0; + + // Called when a low-latency audio stream has been created in the browser + // process. + virtual void OnLowLatencyCreated(base::SharedMemoryHandle handle, + base::SyncSocket::Handle socket_handle, + uint32 length) = 0; + + // Called when notification of stream volume is received from the browser + // process. + virtual void OnVolume(double volume) = 0; + + protected: + virtual ~Delegate() {} + }; + + explicit AudioMessageFilter(int32 route_id); + ~AudioMessageFilter(); + + // Add a delegate to the map and return id of the entry. + int32 AddDelegate(Delegate* delegate); + + // Remove a delegate referenced by |id| from the map. + void RemoveDelegate(int32 id); + + // Sends an IPC message using |channel_|. + bool Send(IPC::Message* message); + + MessageLoop* message_loop() { return message_loop_; } + + private: + // For access to |message_loop_|. + friend class AudioRendererImplTest; + + FRIEND_TEST_ALL_PREFIXES(AudioMessageFilterTest, Basic); + FRIEND_TEST_ALL_PREFIXES(AudioMessageFilterTest, Delegates); + + // IPC::ChannelProxy::MessageFilter override. Called on IO thread. + virtual bool OnMessageReceived(const IPC::Message& message); + virtual void OnFilterAdded(IPC::Channel* channel); + virtual void OnFilterRemoved(); + virtual void OnChannelClosing(); + + // Received when browser process wants more audio packet. + void OnRequestPacket(const IPC::Message& msg, int stream_id, + AudioBuffersState buffers_state); + + // Received when browser process has created an audio output stream. + void OnStreamCreated(int stream_id, base::SharedMemoryHandle handle, + uint32 length); + + // Received when browser process has created an audio output stream of low + // latency. + void OnLowLatencyStreamCreated(int stream_id, base::SharedMemoryHandle handle, +#if defined(OS_WIN) + base::SyncSocket::Handle socket_handle, +#else + base::FileDescriptor socket_descriptor, +#endif + uint32 length); + + + // Received when internal state of browser process' audio output device has + // changed. + void OnStreamStateChanged(int stream_id, + const ViewMsg_AudioStreamState_Params& state); + + // Notification of volume property of an audio output stream. + void OnStreamVolume(int stream_id, double volume); + + // A map of stream ids to delegates. + IDMap<Delegate> delegates_; + + IPC::Channel* channel_; + + int32 route_id_; + + MessageLoop* message_loop_; + + DISALLOW_COPY_AND_ASSIGN(AudioMessageFilter); +}; + +#endif // CONTENT_RENDERER_AUDIO_MESSAGE_FILTER_H_ diff --git a/content/renderer/audio_message_filter_unittest.cc b/content/renderer/audio_message_filter_unittest.cc new file mode 100644 index 0000000..bfd42eb --- /dev/null +++ b/content/renderer/audio_message_filter_unittest.cc @@ -0,0 +1,200 @@ +// Copyright (c) 2010 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 "base/message_loop.h" +#include "chrome/common/render_messages.h" +#include "chrome/common/render_messages_params.h" +#include "content/renderer/audio_message_filter.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +class MockAudioDelegate : public AudioMessageFilter::Delegate { + public: + MockAudioDelegate() { + Reset(); + } + + virtual void OnRequestPacket(AudioBuffersState buffers_state) { + request_packet_received_ = true; + buffers_state_ = buffers_state; + } + + virtual void OnStateChanged(const ViewMsg_AudioStreamState_Params& state) { + state_changed_received_ = true; + state_ = state; + } + + virtual void OnCreated(base::SharedMemoryHandle handle, uint32 length) { + created_received_ = true; + handle_ = handle; + length_ = length; + } + + virtual void OnLowLatencyCreated(base::SharedMemoryHandle handle, + base::SyncSocket::Handle, + uint32 length) { + } + + virtual void OnVolume(double volume) { + volume_received_ = true; + volume_ = volume; + } + + void Reset() { + request_packet_received_ = false; + buffers_state_ = AudioBuffersState(); + buffers_state_.timestamp = base::Time(); + + state_changed_received_ = false; + state_.state = ViewMsg_AudioStreamState_Params::kError; + + created_received_ = false; + handle_ = base::SharedMemory::NULLHandle(); + length_ = 0; + + volume_received_ = false; + volume_ = 0; + } + + bool request_packet_received() { return request_packet_received_; } + AudioBuffersState buffers_state() { return buffers_state_; } + + bool state_changed_received() { return state_changed_received_; } + ViewMsg_AudioStreamState_Params state() { return state_; } + + bool created_received() { return created_received_; } + base::SharedMemoryHandle handle() { return handle_; } + uint32 length() { return length_; } + + bool volume_received() { return volume_received_; } + double volume() { return volume_; } + + private: + bool request_packet_received_; + AudioBuffersState buffers_state_; + + bool state_changed_received_; + ViewMsg_AudioStreamState_Params state_; + + bool created_received_; + base::SharedMemoryHandle handle_; + uint32 length_; + + bool volume_received_; + double volume_; + + DISALLOW_COPY_AND_ASSIGN(MockAudioDelegate); +}; + +} // namespace + +TEST(AudioMessageFilterTest, Basic) { + MessageLoop message_loop(MessageLoop::TYPE_IO); + + const int kRouteId = 0; + scoped_refptr<AudioMessageFilter> filter(new AudioMessageFilter(kRouteId)); + + MockAudioDelegate delegate; + int stream_id = filter->AddDelegate(&delegate); + + // ViewMsg_RequestAudioPacket + const int kSizeInBuffer = 1024; + AudioBuffersState buffers_state(kSizeInBuffer, 0); + + EXPECT_FALSE(delegate.request_packet_received()); + filter->OnMessageReceived(ViewMsg_RequestAudioPacket( + kRouteId, stream_id, buffers_state)); + EXPECT_TRUE(delegate.request_packet_received()); + EXPECT_EQ(kSizeInBuffer, delegate.buffers_state().pending_bytes); + EXPECT_EQ(0, delegate.buffers_state().hardware_delay_bytes); + EXPECT_TRUE(buffers_state.timestamp == delegate.buffers_state().timestamp); + delegate.Reset(); + + // ViewMsg_NotifyAudioStreamStateChanged + const ViewMsg_AudioStreamState_Params kState( + ViewMsg_AudioStreamState_Params::kPlaying); + EXPECT_FALSE(delegate.state_changed_received()); + filter->OnMessageReceived( + ViewMsg_NotifyAudioStreamStateChanged(kRouteId, stream_id, kState)); + EXPECT_TRUE(delegate.state_changed_received()); + EXPECT_TRUE(kState.state == delegate.state().state); + delegate.Reset(); + + // ViewMsg_NotifyAudioStreamCreated + const uint32 kLength = 1024; + EXPECT_FALSE(delegate.created_received()); + filter->OnMessageReceived( + ViewMsg_NotifyAudioStreamCreated(kRouteId, + stream_id, + base::SharedMemory::NULLHandle(), + kLength)); + EXPECT_TRUE(delegate.created_received()); + EXPECT_FALSE(base::SharedMemory::IsHandleValid(delegate.handle())); + EXPECT_EQ(kLength, delegate.length()); + delegate.Reset(); + + // ViewMsg_NotifyAudioStreamVolume + const double kVolume = 1.0; + EXPECT_FALSE(delegate.volume_received()); + filter->OnMessageReceived( + ViewMsg_NotifyAudioStreamVolume(kRouteId, stream_id, kVolume)); + EXPECT_TRUE(delegate.volume_received()); + EXPECT_EQ(kVolume, delegate.volume()); + delegate.Reset(); + + message_loop.RunAllPending(); +} + +TEST(AudioMessageFilterTest, Delegates) { + MessageLoop message_loop(MessageLoop::TYPE_IO); + + const int kRouteId = 0; + scoped_refptr<AudioMessageFilter> filter(new AudioMessageFilter(kRouteId)); + + MockAudioDelegate delegate1; + MockAudioDelegate delegate2; + + int stream_id1 = filter->AddDelegate(&delegate1); + int stream_id2 = filter->AddDelegate(&delegate2); + + // Send an IPC message. Make sure the correct delegate gets called. + EXPECT_FALSE(delegate1.request_packet_received()); + EXPECT_FALSE(delegate2.request_packet_received()); + filter->OnMessageReceived( + ViewMsg_RequestAudioPacket(kRouteId, stream_id1, AudioBuffersState())); + EXPECT_TRUE(delegate1.request_packet_received()); + EXPECT_FALSE(delegate2.request_packet_received()); + delegate1.Reset(); + + EXPECT_FALSE(delegate1.request_packet_received()); + EXPECT_FALSE(delegate2.request_packet_received()); + filter->OnMessageReceived( + ViewMsg_RequestAudioPacket(kRouteId, stream_id2, AudioBuffersState())); + EXPECT_FALSE(delegate1.request_packet_received()); + EXPECT_TRUE(delegate2.request_packet_received()); + delegate2.Reset(); + + // Send a message of a different route id, a message is not received. + EXPECT_FALSE(delegate1.request_packet_received()); + filter->OnMessageReceived( + ViewMsg_RequestAudioPacket(kRouteId + 1, stream_id1, + AudioBuffersState())); + EXPECT_FALSE(delegate1.request_packet_received()); + + // Remove the delegates. Make sure they won't get called. + filter->RemoveDelegate(stream_id1); + EXPECT_FALSE(delegate1.request_packet_received()); + filter->OnMessageReceived( + ViewMsg_RequestAudioPacket(kRouteId, stream_id1, AudioBuffersState())); + EXPECT_FALSE(delegate1.request_packet_received()); + + filter->RemoveDelegate(stream_id2); + EXPECT_FALSE(delegate2.request_packet_received()); + filter->OnMessageReceived( + ViewMsg_RequestAudioPacket(kRouteId, stream_id2, AudioBuffersState())); + EXPECT_FALSE(delegate2.request_packet_received()); + + message_loop.RunAllPending(); +} diff --git a/content/renderer/cookie_message_filter.cc b/content/renderer/cookie_message_filter.cc new file mode 100644 index 0000000..06083c1 --- /dev/null +++ b/content/renderer/cookie_message_filter.cc @@ -0,0 +1,19 @@ +// Copyright (c) 2010 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/renderer/cookie_message_filter.h" + +#include "chrome/common/render_messages.h" + +CookieMessageFilter::CookieMessageFilter() + : event_(true, false) { +} + +bool CookieMessageFilter::OnMessageReceived(const IPC::Message& message) { + if (message.type() == ViewMsg_SignalCookiePromptEvent::ID) { + event_.Signal(); + return true; + } + return false; +} diff --git a/content/renderer/cookie_message_filter.h b/content/renderer/cookie_message_filter.h new file mode 100644 index 0000000..3d0f6df --- /dev/null +++ b/content/renderer/cookie_message_filter.h @@ -0,0 +1,30 @@ +// Copyright (c) 2010 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_RENDERER_COOKIE_MESSAGE_FILTER_H_ +#define CONTENT_RENDERER_COOKIE_MESSAGE_FILTER_H_ +#pragma once + +#include "base/synchronization/waitable_event.h" +#include "ipc/ipc_channel_proxy.h" + +// This class maintains a WaitableEvent that is signaled when an IPC to query +// cookies from the browser should pump events. Pumping events may be +// necessary to avoid deadlocks if the browser blocks the cookie query on a +// user prompt. +class CookieMessageFilter : public IPC::ChannelProxy::MessageFilter { + public: + CookieMessageFilter(); + + base::WaitableEvent* pump_messages_event() { return &event_; } + void ResetPumpMessagesEvent() { event_.Reset(); } + + private: + // IPC::ChannelProxy::MessageFilter implementation: + virtual bool OnMessageReceived(const IPC::Message& message); + + base::WaitableEvent event_; +}; + +#endif // CONTENT_RENDERER_COOKIE_MESSAGE_FILTER_H_ diff --git a/content/renderer/device_orientation_dispatcher.cc b/content/renderer/device_orientation_dispatcher.cc new file mode 100644 index 0000000..309a3e8 --- /dev/null +++ b/content/renderer/device_orientation_dispatcher.cc @@ -0,0 +1,91 @@ +// Copyright (c) 2010 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/renderer/device_orientation_dispatcher.h" + +#include "chrome/common/render_messages.h" +#include "chrome/common/render_messages_params.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebDeviceOrientation.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebDeviceOrientationController.h" + +DeviceOrientationDispatcher::DeviceOrientationDispatcher( + RenderView* render_view) + : RenderViewObserver(render_view), + controller_(NULL), + started_(false) { +} + +DeviceOrientationDispatcher::~DeviceOrientationDispatcher() { + if (started_) + stopUpdating(); +} + +bool DeviceOrientationDispatcher::OnMessageReceived(const IPC::Message& msg) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(DeviceOrientationDispatcher, msg) + IPC_MESSAGE_HANDLER(ViewMsg_DeviceOrientationUpdated, + OnDeviceOrientationUpdated) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +void DeviceOrientationDispatcher::setController( + WebKit::WebDeviceOrientationController* controller) { + controller_.reset(controller); +} + +void DeviceOrientationDispatcher::startUpdating() { + Send(new ViewHostMsg_DeviceOrientation_StartUpdating(routing_id())); + started_ = true; +} + +void DeviceOrientationDispatcher::stopUpdating() { + Send(new ViewHostMsg_DeviceOrientation_StopUpdating(routing_id())); + started_ = false; +} + +WebKit::WebDeviceOrientation DeviceOrientationDispatcher::lastOrientation() + const { + if (!last_orientation_.get()) + return WebKit::WebDeviceOrientation::nullOrientation(); + + return *last_orientation_; +} + +namespace { +bool OrientationsEqual(const ViewMsg_DeviceOrientationUpdated_Params& a, + WebKit::WebDeviceOrientation* b) { + if (a.can_provide_alpha != b->canProvideAlpha()) + return false; + if (a.can_provide_alpha && a.alpha != b->alpha()) + return false; + if (a.can_provide_beta != b->canProvideBeta()) + return false; + if (a.can_provide_beta && a.beta != b->beta()) + return false; + if (a.can_provide_gamma != b->canProvideGamma()) + return false; + if (a.can_provide_gamma && a.gamma != b->gamma()) + return false; + + return true; +} +} // namespace + +void DeviceOrientationDispatcher::OnDeviceOrientationUpdated( + const ViewMsg_DeviceOrientationUpdated_Params& p) { + + if (last_orientation_.get() && OrientationsEqual(p, last_orientation_.get())) + return; + + last_orientation_.reset(new WebKit::WebDeviceOrientation(p.can_provide_alpha, + p.alpha, + p.can_provide_beta, + p.beta, + p.can_provide_gamma, + p.gamma)); + + controller_->didChangeDeviceOrientation(*last_orientation_); +} diff --git a/content/renderer/device_orientation_dispatcher.h b/content/renderer/device_orientation_dispatcher.h new file mode 100644 index 0000000..a50a94f --- /dev/null +++ b/content/renderer/device_orientation_dispatcher.h @@ -0,0 +1,42 @@ +// Copyright (c) 2010 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_RENDERER_DEVICE_ORIENTATION_DISPATCHER_H_ +#define CONTENT_RENDERER_DEVICE_ORIENTATION_DISPATCHER_H_ + +#include "third_party/WebKit/Source/WebKit/chromium/public/WebDeviceOrientationClient.h" + +#include "base/scoped_ptr.h" +#include "chrome/renderer/render_view_observer.h" + +namespace WebKit { class WebDeviceOrientation; } + +struct ViewMsg_DeviceOrientationUpdated_Params; + +class DeviceOrientationDispatcher : public RenderViewObserver, + public WebKit::WebDeviceOrientationClient { + public: + explicit DeviceOrientationDispatcher(RenderView* render_view); + virtual ~DeviceOrientationDispatcher(); + + private: + // RenderView::Observer implementation. + virtual bool OnMessageReceived(const IPC::Message& message); + + // From WebKit::WebDeviceOrientationClient. + virtual void setController( + WebKit::WebDeviceOrientationController* controller); + virtual void startUpdating(); + virtual void stopUpdating(); + virtual WebKit::WebDeviceOrientation lastOrientation() const; + + void OnDeviceOrientationUpdated( + const ViewMsg_DeviceOrientationUpdated_Params& p); + + scoped_ptr<WebKit::WebDeviceOrientationController> controller_; + scoped_ptr<WebKit::WebDeviceOrientation> last_orientation_; + bool started_; +}; + +#endif // CONTENT_RENDERER_DEVICE_ORIENTATION_DISPATCHER_H_ diff --git a/content/renderer/geolocation_dispatcher.cc b/content/renderer/geolocation_dispatcher.cc new file mode 100644 index 0000000..0934aad --- /dev/null +++ b/content/renderer/geolocation_dispatcher.cc @@ -0,0 +1,149 @@ +// Copyright (c) 2010 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/renderer/geolocation_dispatcher.h" + +#include "chrome/common/render_messages.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebGeolocationPermissionRequest.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebGeolocationPermissionRequestManager.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebGeolocationClient.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebGeolocationPosition.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebGeolocationError.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h" + +using namespace WebKit; + +GeolocationDispatcher::GeolocationDispatcher(RenderView* render_view) + : RenderViewObserver(render_view), + pending_permissions_(new WebGeolocationPermissionRequestManager()), + enable_high_accuracy_(false), + updating_(false) { +} + +GeolocationDispatcher::~GeolocationDispatcher() {} + +bool GeolocationDispatcher::OnMessageReceived(const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(GeolocationDispatcher, message) + IPC_MESSAGE_HANDLER(ViewMsg_Geolocation_PermissionSet, + OnGeolocationPermissionSet) + IPC_MESSAGE_HANDLER(ViewMsg_Geolocation_PositionUpdated, + OnGeolocationPositionUpdated) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +void GeolocationDispatcher::geolocationDestroyed() { + controller_.reset(); + DCHECK(!updating_); +} + +void GeolocationDispatcher::startUpdating() { + GURL url; + Send(new ViewHostMsg_Geolocation_StartUpdating( + routing_id(), url, enable_high_accuracy_)); + updating_ = true; +} + +void GeolocationDispatcher::stopUpdating() { + Send(new ViewHostMsg_Geolocation_StopUpdating(routing_id())); + updating_ = false; +} + +void GeolocationDispatcher::setEnableHighAccuracy(bool enable_high_accuracy) { + // GeolocationController calls setEnableHighAccuracy(true) before + // startUpdating in response to the first high-accuracy Geolocation + // subscription. When the last high-accuracy Geolocation unsubscribes + // it calls setEnableHighAccuracy(false) after stopUpdating. + bool has_changed = enable_high_accuracy_ != enable_high_accuracy; + enable_high_accuracy_ = enable_high_accuracy; + // We have a different accuracy requirement. Request browser to update. + if (updating_ && has_changed) + startUpdating(); +} + +void GeolocationDispatcher::setController( + WebGeolocationController* controller) { + controller_.reset(controller); +} + +bool GeolocationDispatcher::lastPosition(WebGeolocationPosition&) { + // The latest position is stored in the browser, not the renderer, so we + // would have to fetch it synchronously to give a good value here. The + // WebCore::GeolocationController already caches the last position it + // receives, so there is not much benefit to more position caching here. + return false; +} + +// TODO(jknotten): Change the messages to use a security origin, so no +// conversion is necessary. +void GeolocationDispatcher::requestPermission( + const WebGeolocationPermissionRequest& permissionRequest) { + int bridge_id = pending_permissions_->add(permissionRequest); + string16 origin = permissionRequest.securityOrigin().toString(); + Send(new ViewHostMsg_Geolocation_RequestPermission( + routing_id(), bridge_id, GURL(origin))); +} + +// TODO(jknotten): Change the messages to use a security origin, so no +// conversion is necessary. +void GeolocationDispatcher::cancelPermissionRequest( + const WebGeolocationPermissionRequest& permissionRequest) { + int bridge_id; + if (!pending_permissions_->remove(permissionRequest, bridge_id)) + return; + string16 origin = permissionRequest.securityOrigin().toString(); + Send(new ViewHostMsg_Geolocation_CancelPermissionRequest( + routing_id(), bridge_id, GURL(origin))); +} + +// Permission for using geolocation has been set. +void GeolocationDispatcher::OnGeolocationPermissionSet( + int bridge_id, bool is_allowed) { + WebGeolocationPermissionRequest permissionRequest; + if (!pending_permissions_->remove(bridge_id, permissionRequest)) + return; + permissionRequest.setIsAllowed(is_allowed); +} + +// We have an updated geolocation position or error code. +void GeolocationDispatcher::OnGeolocationPositionUpdated( + const Geoposition& geoposition) { + // It is possible for the browser process to have queued an update message + // before receiving the stop updating message. + if (!updating_) + return; + + DCHECK(geoposition.IsInitialized()); + if (geoposition.IsValidFix()) { + controller_->positionChanged( + WebGeolocationPosition( + geoposition.timestamp.ToDoubleT(), + geoposition.latitude, geoposition.longitude, + geoposition.accuracy, + geoposition.is_valid_altitude(), geoposition.altitude, + geoposition.is_valid_altitude_accuracy(), + geoposition.altitude_accuracy, + geoposition.is_valid_heading(), geoposition.heading, + geoposition.is_valid_speed(), geoposition.speed)); + } else { + WebGeolocationError::Error code; + switch (geoposition.error_code) { + case Geoposition::ERROR_CODE_PERMISSION_DENIED: + code = WebGeolocationError::ErrorPermissionDenied; + break; + case Geoposition::ERROR_CODE_POSITION_UNAVAILABLE: + code = WebGeolocationError::ErrorPositionUnavailable; + break; + default: + DCHECK(false); + NOTREACHED() << geoposition.error_code; + return; + } + controller_->errorOccurred( + WebGeolocationError( + code, WebKit::WebString::fromUTF8(geoposition.error_message))); + } +} diff --git a/content/renderer/geolocation_dispatcher.h b/content/renderer/geolocation_dispatcher.h new file mode 100644 index 0000000..2189946 --- /dev/null +++ b/content/renderer/geolocation_dispatcher.h @@ -0,0 +1,66 @@ +// Copyright (c) 2010 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_RENDERER_GEOLOCATION_DISPATCHER_H_ +#define CONTENT_RENDERER_GEOLOCATION_DISPATCHER_H_ +#pragma once + +#include "base/scoped_ptr.h" +#include "chrome/renderer/render_view_observer.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebGeolocationClient.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebGeolocationController.h" + +struct Geoposition; + +namespace WebKit { +class WebGeolocationController; +class WebGeolocationPermissionRequest; +class WebGeolocationPermissionRequestManager; +class WebGeolocationPosition; +class WebSecurityOrigin; +} + +// GeolocationDispatcher is a delegate for Geolocation messages used by +// WebKit. +// It's the complement of GeolocationDispatcherHost (owned by RenderViewHost). +class GeolocationDispatcher : public RenderViewObserver, + public WebKit::WebGeolocationClient { + public: + explicit GeolocationDispatcher(RenderView* render_view); + virtual ~GeolocationDispatcher(); + + private: + // RenderView::Observer implementation. + virtual bool OnMessageReceived(const IPC::Message& message); + + // WebGeolocationClient + virtual void geolocationDestroyed(); + virtual void startUpdating(); + virtual void stopUpdating(); + virtual void setEnableHighAccuracy(bool enable_high_accuracy); + virtual void setController(WebKit::WebGeolocationController* controller); + virtual bool lastPosition(WebKit::WebGeolocationPosition& position); + virtual void requestPermission( + const WebKit::WebGeolocationPermissionRequest& permissionRequest); + virtual void cancelPermissionRequest( + const WebKit::WebGeolocationPermissionRequest& permissionRequest); + + // Permission for using geolocation has been set. + void OnGeolocationPermissionSet(int bridge_id, bool is_allowed); + + // We have an updated geolocation position or error code. + void OnGeolocationPositionUpdated(const Geoposition& geoposition); + + // The controller_ is valid for the lifetime of the underlying + // WebCore::GeolocationController. geolocationDestroyed() is + // invoked when the underlying object is destroyed. + scoped_ptr< WebKit::WebGeolocationController> controller_; + + scoped_ptr<WebKit::WebGeolocationPermissionRequestManager> + pending_permissions_; + bool enable_high_accuracy_; + bool updating_; +}; + +#endif // CONTENT_RENDERER_GEOLOCATION_DISPATCHER_H_ diff --git a/content/renderer/indexed_db_dispatcher.cc b/content/renderer/indexed_db_dispatcher.cc new file mode 100644 index 0000000..d62ad6f --- /dev/null +++ b/content/renderer/indexed_db_dispatcher.cc @@ -0,0 +1,455 @@ +// Copyright (c) 2009 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/renderer/indexed_db_dispatcher.h" + +#include "chrome/renderer/render_thread.h" +#include "chrome/renderer/render_view.h" +#include "chrome/renderer/renderer_webidbcursor_impl.h" +#include "chrome/renderer/renderer_webidbdatabase_impl.h" +#include "chrome/renderer/renderer_webidbindex_impl.h" +#include "chrome/renderer/renderer_webidbobjectstore_impl.h" +#include "chrome/renderer/renderer_webidbtransaction_impl.h" +#include "content/common/indexed_db_messages.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBDatabaseCallbacks.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBDatabaseError.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBKeyRange.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebSerializedScriptValue.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h" + +using WebKit::WebExceptionCode; +using WebKit::WebFrame; +using WebKit::WebIDBCallbacks; +using WebKit::WebIDBKeyRange; +using WebKit::WebIDBDatabase; +using WebKit::WebIDBDatabaseCallbacks; +using WebKit::WebIDBDatabaseError; +using WebKit::WebIDBTransaction; +using WebKit::WebIDBTransactionCallbacks; + +IndexedDBDispatcher::IndexedDBDispatcher() { +} + +IndexedDBDispatcher::~IndexedDBDispatcher() { +} + +bool IndexedDBDispatcher::OnMessageReceived(const IPC::Message& msg) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(IndexedDBDispatcher, msg) + IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIDBCursor, + OnSuccessOpenCursor) + IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIDBDatabase, + OnSuccessIDBDatabase) + IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIDBIndex, + OnSuccessIDBIndex) + IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIndexedDBKey, + OnSuccessIndexedDBKey) + IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIDBTransaction, + OnSuccessIDBTransaction) + IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessSerializedScriptValue, + OnSuccessSerializedScriptValue) + IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksError, OnError) + IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksBlocked, OnBlocked) + IPC_MESSAGE_HANDLER(IndexedDBMsg_TransactionCallbacksAbort, OnAbort) + IPC_MESSAGE_HANDLER(IndexedDBMsg_TransactionCallbacksComplete, OnComplete) + IPC_MESSAGE_HANDLER(IndexedDBMsg_TransactionCallbacksTimeout, OnTimeout) + IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksVersionChange, + OnVersionChange) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +void IndexedDBDispatcher::RequestIDBCursorUpdate( + const SerializedScriptValue& value, + WebIDBCallbacks* callbacks_ptr, + int32 idb_cursor_id, + WebExceptionCode* ec) { + scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); + + int32 response_id = pending_callbacks_.Add(callbacks.release()); + RenderThread::current()->Send( + new IndexedDBHostMsg_CursorUpdate(idb_cursor_id, response_id, value, ec)); + if (*ec) + pending_callbacks_.Remove(response_id); +} + +void IndexedDBDispatcher::RequestIDBCursorContinue( + const IndexedDBKey& key, + WebIDBCallbacks* callbacks_ptr, + int32 idb_cursor_id, + WebExceptionCode* ec) { + scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); + + int32 response_id = pending_callbacks_.Add(callbacks.release()); + RenderThread::current()->Send( + new IndexedDBHostMsg_CursorContinue(idb_cursor_id, response_id, key, ec)); + if (*ec) + pending_callbacks_.Remove(response_id); +} + +void IndexedDBDispatcher::RequestIDBCursorDelete( + WebIDBCallbacks* callbacks_ptr, + int32 idb_cursor_id, + WebExceptionCode* ec) { + scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); + + int32 response_id = pending_callbacks_.Add(callbacks.release()); + RenderThread::current()->Send( + new IndexedDBHostMsg_CursorDelete(idb_cursor_id, response_id, ec)); + if (*ec) + pending_callbacks_.Remove(response_id); +} + +void IndexedDBDispatcher::RequestIDBFactoryOpen( + const string16& name, + WebIDBCallbacks* callbacks_ptr, + const string16& origin, + WebFrame* web_frame, + uint64 maximum_size) { + scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); + + if (!web_frame) + return; // We must be shutting down. + RenderView* render_view = RenderView::FromWebView(web_frame->view()); + if (!render_view) + return; // We must be shutting down. + + IndexedDBHostMsg_FactoryOpen_Params params; + params.routing_id = render_view->routing_id(); + params.response_id = pending_callbacks_.Add(callbacks.release()); + params.origin = origin; + params.name = name; + params.maximum_size = maximum_size; + RenderThread::current()->Send(new IndexedDBHostMsg_FactoryOpen(params)); +} + +void IndexedDBDispatcher::RequestIDBFactoryDeleteDatabase( + const string16& name, + WebIDBCallbacks* callbacks_ptr, + const string16& origin, + WebFrame* web_frame) { + scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); + + if (!web_frame) + return; // We must be shutting down. + RenderView* render_view = RenderView::FromWebView(web_frame->view()); + if (!render_view) + return; // We must be shutting down. + + IndexedDBHostMsg_FactoryDeleteDatabase_Params params; + params.routing_id = render_view->routing_id(); + params.response_id = pending_callbacks_.Add(callbacks.release()); + params.origin = origin; + params.name = name; + RenderThread::current()->Send( + new IndexedDBHostMsg_FactoryDeleteDatabase(params)); +} + +void IndexedDBDispatcher::RequestIDBDatabaseClose(int32 idb_database_id) { + RenderThread::current()->Send( + new IndexedDBHostMsg_DatabaseClose(idb_database_id)); + pending_database_callbacks_.Remove(idb_database_id); +} + + void IndexedDBDispatcher::RequestIDBDatabaseOpen( + WebIDBDatabaseCallbacks* callbacks_ptr, + int32 idb_database_id) { + scoped_ptr<WebIDBDatabaseCallbacks> callbacks(callbacks_ptr); + + int32 response_id = pending_database_callbacks_.Add(callbacks.release()); + RenderThread::current()->Send(new IndexedDBHostMsg_DatabaseOpen(response_id, + idb_database_id)); +} + +void IndexedDBDispatcher::RequestIDBDatabaseSetVersion( + const string16& version, + WebIDBCallbacks* callbacks_ptr, + int32 idb_database_id, + WebExceptionCode* ec) { + scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); + + int32 response_id = pending_callbacks_.Add(callbacks.release()); + RenderThread::current()->Send( + new IndexedDBHostMsg_DatabaseSetVersion(idb_database_id, response_id, + version, ec)); + if (*ec) + pending_callbacks_.Remove(response_id); +} + +void IndexedDBDispatcher::RequestIDBIndexOpenObjectCursor( + const WebIDBKeyRange& idb_key_range, + unsigned short direction, + WebIDBCallbacks* callbacks_ptr, + int32 idb_index_id, + const WebIDBTransaction& transaction, + WebExceptionCode* ec) { + scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); + IndexedDBHostMsg_IndexOpenCursor_Params params; + params.response_id = pending_callbacks_.Add(callbacks.release()); + params.lower_key.Set(idb_key_range.lower()); + params.upper_key.Set(idb_key_range.upper()); + params.lower_open = idb_key_range.lowerOpen(); + params.upper_open = idb_key_range.upperOpen(); + params.direction = direction; + params.idb_index_id = idb_index_id; + params.transaction_id = TransactionId(transaction); + RenderThread::current()->Send( + new IndexedDBHostMsg_IndexOpenObjectCursor(params, ec)); + if (*ec) + pending_callbacks_.Remove(params.response_id); +} + +void IndexedDBDispatcher::RequestIDBIndexOpenKeyCursor( + const WebIDBKeyRange& idb_key_range, + unsigned short direction, + WebIDBCallbacks* callbacks_ptr, + int32 idb_index_id, + const WebIDBTransaction& transaction, + WebExceptionCode* ec) { + scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); + IndexedDBHostMsg_IndexOpenCursor_Params params; + params.response_id = pending_callbacks_.Add(callbacks.release()); + // TODO(jorlow): We really should just create a Chromium abstraction for + // KeyRange rather than doing it ad-hoc like this. + params.lower_key.Set(idb_key_range.lower()); + params.upper_key.Set(idb_key_range.upper()); + params.lower_open = idb_key_range.lowerOpen(); + params.upper_open = idb_key_range.upperOpen(); + params.direction = direction; + params.idb_index_id = idb_index_id; + params.transaction_id = TransactionId(transaction); + RenderThread::current()->Send( + new IndexedDBHostMsg_IndexOpenKeyCursor(params, ec)); + if (*ec) + pending_callbacks_.Remove(params.response_id); +} + +void IndexedDBDispatcher::RequestIDBIndexGetObject( + const IndexedDBKey& key, + WebIDBCallbacks* callbacks_ptr, + int32 idb_index_id, + const WebIDBTransaction& transaction, + WebExceptionCode* ec) { + scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); + int32 response_id = pending_callbacks_.Add(callbacks.release()); + RenderThread::current()->Send( + new IndexedDBHostMsg_IndexGetObject( + idb_index_id, response_id, key, + TransactionId(transaction), ec)); + if (*ec) + pending_callbacks_.Remove(response_id); +} + +void IndexedDBDispatcher::RequestIDBIndexGetKey( + const IndexedDBKey& key, + WebIDBCallbacks* callbacks_ptr, + int32 idb_index_id, + const WebIDBTransaction& transaction, + WebExceptionCode* ec) { + scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); + int32 response_id = pending_callbacks_.Add(callbacks.release()); + RenderThread::current()->Send( + new IndexedDBHostMsg_IndexGetKey( + idb_index_id, response_id, key, + TransactionId(transaction), ec)); + if (*ec) + pending_callbacks_.Remove(response_id); +} + +void IndexedDBDispatcher::RequestIDBObjectStoreGet( + const IndexedDBKey& key, + WebIDBCallbacks* callbacks_ptr, + int32 idb_object_store_id, + const WebIDBTransaction& transaction, + WebExceptionCode* ec) { + scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); + + int32 response_id = pending_callbacks_.Add(callbacks.release()); + RenderThread::current()->Send( + new IndexedDBHostMsg_ObjectStoreGet( + idb_object_store_id, response_id, + key, TransactionId(transaction), ec)); + if (*ec) + pending_callbacks_.Remove(response_id); +} + +void IndexedDBDispatcher::RequestIDBObjectStorePut( + const SerializedScriptValue& value, + const IndexedDBKey& key, + WebKit::WebIDBObjectStore::PutMode put_mode, + WebIDBCallbacks* callbacks_ptr, + int32 idb_object_store_id, + const WebIDBTransaction& transaction, + WebExceptionCode* ec) { + scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); + IndexedDBHostMsg_ObjectStorePut_Params params; + params.idb_object_store_id = idb_object_store_id; + params.response_id = pending_callbacks_.Add(callbacks.release()); + params.serialized_value = value; + params.key = key; + params.put_mode = put_mode; + params.transaction_id = TransactionId(transaction); + RenderThread::current()->Send(new IndexedDBHostMsg_ObjectStorePut( + params, ec)); + if (*ec) + pending_callbacks_.Remove(params.response_id); +} + +void IndexedDBDispatcher::RequestIDBObjectStoreDelete( + const IndexedDBKey& key, + WebIDBCallbacks* callbacks_ptr, + int32 idb_object_store_id, + const WebIDBTransaction& transaction, + WebExceptionCode* ec) { + scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); + + int32 response_id = pending_callbacks_.Add(callbacks.release()); + RenderThread::current()->Send( + new IndexedDBHostMsg_ObjectStoreDelete( + idb_object_store_id, response_id, + key, TransactionId(transaction), ec)); + if (*ec) + pending_callbacks_.Remove(response_id); +} + +void IndexedDBDispatcher::RequestIDBObjectStoreClear( + WebIDBCallbacks* callbacks_ptr, + int32 idb_object_store_id, + const WebIDBTransaction& transaction, + WebExceptionCode* ec) { + scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); + + int32 response_id = pending_callbacks_.Add(callbacks.release()); + RenderThread::current()->Send( + new IndexedDBHostMsg_ObjectStoreClear( + idb_object_store_id, response_id, + TransactionId(transaction), ec)); + if (*ec) + pending_callbacks_.Remove(response_id); +} + +void IndexedDBDispatcher::RequestIDBObjectStoreOpenCursor( + const WebIDBKeyRange& idb_key_range, + unsigned short direction, + WebIDBCallbacks* callbacks_ptr, + int32 idb_object_store_id, + const WebIDBTransaction& transaction, + WebExceptionCode* ec) { + scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); + IndexedDBHostMsg_ObjectStoreOpenCursor_Params params; + params.response_id = pending_callbacks_.Add(callbacks.release()); + params.lower_key.Set(idb_key_range.lower()); + params.upper_key.Set(idb_key_range.upper()); + params.lower_open = idb_key_range.lowerOpen(); + params.upper_open = idb_key_range.upperOpen(); + params.direction = direction; + params.idb_object_store_id = idb_object_store_id; + params.transaction_id = TransactionId(transaction); + RenderThread::current()->Send( + new IndexedDBHostMsg_ObjectStoreOpenCursor(params, ec)); + if (*ec) + pending_callbacks_.Remove(params.response_id); +} + +void IndexedDBDispatcher::RegisterWebIDBTransactionCallbacks( + WebIDBTransactionCallbacks* callbacks, + int32 id) { + pending_transaction_callbacks_.AddWithID(callbacks, id); +} + +int32 IndexedDBDispatcher::TransactionId( + const WebIDBTransaction& transaction) { + const RendererWebIDBTransactionImpl* impl = + static_cast<const RendererWebIDBTransactionImpl*>(&transaction); + return impl->id(); +} + +void IndexedDBDispatcher::OnSuccessIDBDatabase(int32 response_id, + int32 object_id) { + WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(response_id); + callbacks->onSuccess(new RendererWebIDBDatabaseImpl(object_id)); + pending_callbacks_.Remove(response_id); +} + +void IndexedDBDispatcher::OnSuccessIndexedDBKey(int32 response_id, + const IndexedDBKey& key) { + WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(response_id); + callbacks->onSuccess(key); + pending_callbacks_.Remove(response_id); +} + +void IndexedDBDispatcher::OnSuccessIDBTransaction(int32 response_id, + int32 object_id) { + WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(response_id); + callbacks->onSuccess(new RendererWebIDBTransactionImpl(object_id)); + pending_callbacks_.Remove(response_id); +} + +void IndexedDBDispatcher::OnSuccessIDBIndex(int32 response_id, + int32 object_id) { + WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(response_id); + callbacks->onSuccess(new RendererWebIDBIndexImpl(object_id)); + pending_callbacks_.Remove(response_id); +} + +void IndexedDBDispatcher::OnSuccessSerializedScriptValue( + int32 response_id, const SerializedScriptValue& value) { + WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(response_id); + callbacks->onSuccess(value); + pending_callbacks_.Remove(response_id); +} + +void IndexedDBDispatcher::OnSuccessOpenCursor(int32 repsonse_id, + int32 object_id) { + WebIDBCallbacks* callbacks = + pending_callbacks_.Lookup(repsonse_id); + callbacks->onSuccess(new RendererWebIDBCursorImpl(object_id)); + pending_callbacks_.Remove(repsonse_id); +} + +void IndexedDBDispatcher::OnBlocked(int32 response_id) { + WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(response_id); + callbacks->onBlocked(); +} + +void IndexedDBDispatcher::OnError(int32 response_id, int code, + const string16& message) { + WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(response_id); + callbacks->onError(WebIDBDatabaseError(code, message)); + pending_callbacks_.Remove(response_id); +} + +void IndexedDBDispatcher::OnAbort(int32 transaction_id) { + WebIDBTransactionCallbacks* callbacks = + pending_transaction_callbacks_.Lookup(transaction_id); + callbacks->onAbort(); + pending_transaction_callbacks_.Remove(transaction_id); +} + +void IndexedDBDispatcher::OnComplete(int32 transaction_id) { + WebIDBTransactionCallbacks* callbacks = + pending_transaction_callbacks_.Lookup(transaction_id); + callbacks->onComplete(); + pending_transaction_callbacks_.Remove(transaction_id); +} + +void IndexedDBDispatcher::OnTimeout(int32 transaction_id) { + WebIDBTransactionCallbacks* callbacks = + pending_transaction_callbacks_.Lookup(transaction_id); + callbacks->onTimeout(); + pending_transaction_callbacks_.Remove(transaction_id); +} + +void IndexedDBDispatcher::OnVersionChange(int32 database_id, + const string16& newVersion) { + WebIDBDatabaseCallbacks* callbacks = + pending_database_callbacks_.Lookup(database_id); + // callbacks would be NULL if a versionchange event is received after close + // has been called. + if (callbacks) + callbacks->onVersionChange(newVersion); +} diff --git a/content/renderer/indexed_db_dispatcher.h b/content/renderer/indexed_db_dispatcher.h new file mode 100644 index 0000000..b019510 --- /dev/null +++ b/content/renderer/indexed_db_dispatcher.h @@ -0,0 +1,176 @@ +// Copyright (c) 2010 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_RENDERER_INDEXED_DB_DISPATCHER_H_ +#define CONTENT_RENDERER_INDEXED_DB_DISPATCHER_H_ +#pragma once + +#include "base/id_map.h" +#include "base/nullable_string16.h" +#include "ipc/ipc_channel.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebExceptionCode.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBCallbacks.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBDatabase.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBObjectStore.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBTransactionCallbacks.h" + +class IndexedDBKey; +class SerializedScriptValue; + +namespace WebKit { +class WebFrame; +class WebIDBKeyRange; +class WebIDBTransaction; +} + +// Handle the indexed db related communication for this entire renderer. +class IndexedDBDispatcher : public IPC::Channel::Listener { + public: + IndexedDBDispatcher(); + ~IndexedDBDispatcher(); + + // IPC::Channel::Listener implementation. + virtual bool OnMessageReceived(const IPC::Message& msg); + + void RequestIDBFactoryOpen( + const string16& name, + WebKit::WebIDBCallbacks* callbacks, + const string16& origin, + WebKit::WebFrame* web_frame, + uint64 maximum_size); + + void RequestIDBFactoryDeleteDatabase( + const string16& name, + WebKit::WebIDBCallbacks* callbacks, + const string16& origin, + WebKit::WebFrame* web_frame); + + void RequestIDBCursorUpdate( + const SerializedScriptValue& value, + WebKit::WebIDBCallbacks* callbacks_ptr, + int32 idb_cursor_id, + WebKit::WebExceptionCode* ec); + + void RequestIDBCursorContinue( + const IndexedDBKey& key, + WebKit::WebIDBCallbacks* callbacks_ptr, + int32 idb_cursor_id, + WebKit::WebExceptionCode* ec); + + void RequestIDBCursorDelete( + WebKit::WebIDBCallbacks* callbacks_ptr, + int32 idb_cursor_id, + WebKit::WebExceptionCode* ec); + + void RequestIDBDatabaseClose( + int32 idb_database_id); + + void RequestIDBDatabaseOpen( + WebKit::WebIDBDatabaseCallbacks* callbacks_ptr, + int32 idb_database_id); + + void RequestIDBDatabaseSetVersion( + const string16& version, + WebKit::WebIDBCallbacks* callbacks, + int32 idb_database_id, + WebKit::WebExceptionCode* ec); + + void RequestIDBIndexOpenObjectCursor( + const WebKit::WebIDBKeyRange& idb_key_range, + unsigned short direction, + WebKit::WebIDBCallbacks* callbacks, + int32 idb_index_id, + const WebKit::WebIDBTransaction& transaction, + WebKit::WebExceptionCode* ec); + + void RequestIDBIndexOpenKeyCursor( + const WebKit::WebIDBKeyRange& idb_key_range, + unsigned short direction, + WebKit::WebIDBCallbacks* callbacks, + int32 idb_index_id, + const WebKit::WebIDBTransaction& transaction, + WebKit::WebExceptionCode* ec); + + void RequestIDBIndexGetObject(const IndexedDBKey& key, + WebKit::WebIDBCallbacks* callbacks, + int32 idb_index_id, + const WebKit::WebIDBTransaction& transaction, + WebKit::WebExceptionCode* ec); + + void RequestIDBIndexGetKey(const IndexedDBKey& key, + WebKit::WebIDBCallbacks* callbacks, + int32 idb_index_id, + const WebKit::WebIDBTransaction& transaction, + WebKit::WebExceptionCode* ec); + + void RequestIDBObjectStoreGet(const IndexedDBKey& key, + WebKit::WebIDBCallbacks* callbacks, + int32 idb_object_store_id, + const WebKit::WebIDBTransaction& transaction, + WebKit::WebExceptionCode* ec); + + void RequestIDBObjectStorePut(const SerializedScriptValue& value, + const IndexedDBKey& key, + WebKit::WebIDBObjectStore::PutMode putMode, + WebKit::WebIDBCallbacks* callbacks, + int32 idb_object_store_id, + const WebKit::WebIDBTransaction& transaction, + WebKit::WebExceptionCode* ec); + + void RequestIDBObjectStoreDelete( + const IndexedDBKey& key, + WebKit::WebIDBCallbacks* callbacks, + int32 idb_object_store_id, + const WebKit::WebIDBTransaction& transaction, + WebKit::WebExceptionCode* ec); + + void RequestIDBObjectStoreClear( + WebKit::WebIDBCallbacks* callbacks, + int32 idb_object_store_id, + const WebKit::WebIDBTransaction& transaction, + WebKit::WebExceptionCode* ec); + + void RequestIDBObjectStoreOpenCursor( + const WebKit::WebIDBKeyRange& idb_key_range, + unsigned short direction, + WebKit::WebIDBCallbacks* callbacks, + int32 idb_object_store_id, + const WebKit::WebIDBTransaction& transaction, + WebKit::WebExceptionCode* ec); + + void RegisterWebIDBTransactionCallbacks( + WebKit::WebIDBTransactionCallbacks* callbacks, + int32 id); + + static int32 TransactionId(const WebKit::WebIDBTransaction& transaction); + + private: + // IDBCallback message handlers. + void OnSuccessNull(int32 response_id); + void OnSuccessIDBDatabase(int32 response_id, int32 object_id); + void OnSuccessIndexedDBKey(int32 response_id, const IndexedDBKey& key); + void OnSuccessIDBTransaction(int32 response_id, int32 object_id); + void OnSuccessIDBIndex(int32 response_id, int32 object_id); + void OnSuccessOpenCursor(int32 response_id, int32 object_id); + void OnSuccessSerializedScriptValue(int32 response_id, + const SerializedScriptValue& value); + void OnError(int32 response_id, int code, const string16& message); + void OnBlocked(int32 response_id); + void OnAbort(int32 transaction_id); + void OnComplete(int32 transaction_id); + void OnTimeout(int32 transaction_id); + void OnVersionChange(int32 database_id, const string16& newVersion); + + // Careful! WebIDBCallbacks wraps non-threadsafe data types. It must be + // destroyed and used on the same thread it was created on. + IDMap<WebKit::WebIDBCallbacks, IDMapOwnPointer> pending_callbacks_; + IDMap<WebKit::WebIDBTransactionCallbacks, IDMapOwnPointer> + pending_transaction_callbacks_; + IDMap<WebKit::WebIDBDatabaseCallbacks, IDMapOwnPointer> + pending_database_callbacks_; + + DISALLOW_COPY_AND_ASSIGN(IndexedDBDispatcher); +}; + +#endif // CONTENT_RENDERER_INDEXED_DB_DISPATCHER_H_ diff --git a/content/renderer/media/audio_renderer_impl.cc b/content/renderer/media/audio_renderer_impl.cc index 86338e9..411a1d6 100644 --- a/content/renderer/media/audio_renderer_impl.cc +++ b/content/renderer/media/audio_renderer_impl.cc @@ -8,7 +8,6 @@ #include "chrome/common/render_messages.h" #include "chrome/common/render_messages_params.h" -#include "chrome/renderer/audio_message_filter.h" #include "chrome/renderer/render_view.h" #include "chrome/renderer/render_thread.h" #include "media/base/filter_host.h" diff --git a/content/renderer/media/audio_renderer_impl.h b/content/renderer/media/audio_renderer_impl.h index c9f11a3..adb9674 100644 --- a/content/renderer/media/audio_renderer_impl.h +++ b/content/renderer/media/audio_renderer_impl.h @@ -43,7 +43,7 @@ #include "base/scoped_ptr.h" #include "base/shared_memory.h" #include "base/synchronization/lock.h" -#include "chrome/renderer/audio_message_filter.h" +#include "content/renderer/audio_message_filter.h" #include "media/audio/audio_io.h" #include "media/audio/audio_manager.h" #include "media/base/filters.h" diff --git a/content/renderer/notification_provider.cc b/content/renderer/notification_provider.cc new file mode 100644 index 0000000..73633fc --- /dev/null +++ b/content/renderer/notification_provider.cc @@ -0,0 +1,188 @@ +// Copyright (c) 2009 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/renderer/notification_provider.h" + +#include "base/string_util.h" +#include "base/task.h" +#include "chrome/common/render_messages.h" +#include "chrome/common/render_messages_params.h" +#include "chrome/common/url_constants.h" +#include "chrome/renderer/render_thread.h" +#include "chrome/renderer/render_view.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebNotificationPermissionCallback.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" + +using WebKit::WebDocument; +using WebKit::WebNotification; +using WebKit::WebNotificationPresenter; +using WebKit::WebNotificationPermissionCallback; +using WebKit::WebSecurityOrigin; +using WebKit::WebString; +using WebKit::WebURL; + +NotificationProvider::NotificationProvider(RenderView* render_view) + : RenderViewObserver(render_view) { +} + +NotificationProvider::~NotificationProvider() { + manager_.DetachAll(); +} + +bool NotificationProvider::show(const WebNotification& notification) { + int notification_id = manager_.RegisterNotification(notification); + if (notification.isHTML()) + return ShowHTML(notification, notification_id); + else + return ShowText(notification, notification_id); +} + +void NotificationProvider::cancel(const WebNotification& notification) { + int id; + bool id_found = manager_.GetId(notification, id); + // Won't be found if the notification has already been closed by the user. + if (id_found) + Send(new ViewHostMsg_CancelDesktopNotification(routing_id(), id)); +} + +void NotificationProvider::objectDestroyed( + const WebNotification& notification) { + int id; + bool id_found = manager_.GetId(notification, id); + // Won't be found if the notification has already been closed by the user. + if (id_found) + manager_.UnregisterNotification(id); +} + +WebNotificationPresenter::Permission NotificationProvider::checkPermission( + const WebURL& url) { + int permission; + Send(new ViewHostMsg_CheckNotificationPermission( + routing_id(), + url, + &permission)); + return static_cast<WebNotificationPresenter::Permission>(permission); +} + +void NotificationProvider::requestPermission( + const WebSecurityOrigin& origin, + WebNotificationPermissionCallback* callback) { + // We only request permission in response to a user gesture. + if (!render_view()->webview()->mainFrame()->isProcessingUserGesture()) + return; + + int id = manager_.RegisterPermissionRequest(callback); + + Send(new ViewHostMsg_RequestNotificationPermission(routing_id(), + GURL(origin.toString()), + id)); +} + +bool NotificationProvider::OnMessageReceived(const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(NotificationProvider, message) + IPC_MESSAGE_HANDLER(ViewMsg_PostDisplayToNotificationObject, OnDisplay); + IPC_MESSAGE_HANDLER(ViewMsg_PostErrorToNotificationObject, OnError); + IPC_MESSAGE_HANDLER(ViewMsg_PostCloseToNotificationObject, OnClose); + IPC_MESSAGE_HANDLER(ViewMsg_PostClickToNotificationObject, OnClick); + IPC_MESSAGE_HANDLER(ViewMsg_PermissionRequestDone, + OnPermissionRequestComplete); + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + + if (message.type() == ViewMsg_Navigate::ID) + OnNavigate(); // Don't want to swallow the message. + + return handled; +} + +bool NotificationProvider::ShowHTML(const WebNotification& notification, + int id) { + // Disallow HTML notifications from unwanted schemes. javascript: + // in particular allows unwanted cross-domain access. + GURL url = notification.url(); + if (!url.SchemeIs(chrome::kHttpScheme) && + !url.SchemeIs(chrome::kHttpsScheme) && + !url.SchemeIs(chrome::kExtensionScheme) && + !url.SchemeIs(chrome::kDataScheme)) + return false; + + DCHECK(notification.isHTML()); + ViewHostMsg_ShowNotification_Params params; + params.origin = + GURL(render_view()->webview()->mainFrame()->url()).GetOrigin(); + params.is_html = true; + params.contents_url = notification.url(); + params.notification_id = id; + params.replace_id = notification.replaceId(); + return Send(new ViewHostMsg_ShowDesktopNotification(routing_id(), params)); +} + +bool NotificationProvider::ShowText(const WebNotification& notification, + int id) { + DCHECK(!notification.isHTML()); + ViewHostMsg_ShowNotification_Params params; + params.is_html = false; + params.origin = GURL( + render_view()->webview()->mainFrame()->url()).GetOrigin(); + params.icon_url = notification.iconURL(); + params.title = notification.title(); + params.body = notification.body(); + params.direction = notification.direction(); + params.notification_id = id; + params.replace_id = notification.replaceId(); + return Send(new ViewHostMsg_ShowDesktopNotification(routing_id(), params)); +} + +void NotificationProvider::OnDisplay(int id) { + WebNotification notification; + bool found = manager_.GetNotification(id, ¬ification); + // |found| may be false if the WebNotification went out of scope in + // the page before it was actually displayed to the user. + if (found) + notification.dispatchDisplayEvent(); +} + +void NotificationProvider::OnError(int id, const WebString& message) { + WebNotification notification; + bool found = manager_.GetNotification(id, ¬ification); + // |found| may be false if the WebNotification went out of scope in + // the page before the error occurred. + if (found) + notification.dispatchErrorEvent(message); +} + +void NotificationProvider::OnClose(int id, bool by_user) { + WebNotification notification; + bool found = manager_.GetNotification(id, ¬ification); + // |found| may be false if the WebNotification went out of scope in + // the page before the associated toast was closed by the user. + if (found) { + notification.dispatchCloseEvent(by_user); + manager_.UnregisterNotification(id); + } +} + +void NotificationProvider::OnClick(int id) { + WebNotification notification; + bool found = manager_.GetNotification(id, ¬ification); + // |found| may be false if the WebNotification went out of scope in + // the page before the associated toast was clicked on. + if (found) + notification.dispatchClickEvent(); +} + +void NotificationProvider::OnPermissionRequestComplete(int id) { + WebNotificationPermissionCallback* callback = manager_.GetCallback(id); + DCHECK(callback); + callback->permissionRequestComplete(); + manager_.OnPermissionRequestComplete(id); +} + +void NotificationProvider::OnNavigate() { + manager_.Clear(); +} diff --git a/content/renderer/notification_provider.h b/content/renderer/notification_provider.h new file mode 100644 index 0000000..32abdee --- /dev/null +++ b/content/renderer/notification_provider.h @@ -0,0 +1,58 @@ +// Copyright (c) 2010 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_RENDERER_NOTIFICATION_PROVIDER_H_ +#define CONTENT_RENDERER_NOTIFICATION_PROVIDER_H_ +#pragma once + +#include "chrome/common/desktop_notifications/active_notification_tracker.h" +#include "chrome/renderer/render_view_observer.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebNotification.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebNotificationPresenter.h" + +namespace WebKit { +class WebNotificationPermissionCallback; +} + +// NotificationProvider class is owned by the RenderView. Only +// to be used on the main thread. +class NotificationProvider : public RenderViewObserver, + public WebKit::WebNotificationPresenter { + public: + explicit NotificationProvider(RenderView* render_view); + virtual ~NotificationProvider(); + + private: + // RenderView::Observer implementation. + virtual bool OnMessageReceived(const IPC::Message& message); + + // WebKit::WebNotificationPresenter interface. + virtual bool show(const WebKit::WebNotification& proxy); + virtual void cancel(const WebKit::WebNotification& proxy); + virtual void objectDestroyed(const WebKit::WebNotification& proxy); + virtual WebKit::WebNotificationPresenter::Permission checkPermission( + const WebKit::WebURL& url); + virtual void requestPermission(const WebKit::WebSecurityOrigin& origin, + WebKit::WebNotificationPermissionCallback* callback); + + // Internal methods used to show notifications. + bool ShowHTML(const WebKit::WebNotification& notification, int id); + bool ShowText(const WebKit::WebNotification& notification, int id); + + // IPC handlers. + void OnDisplay(int id); + void OnError(int id, const WebKit::WebString& message); + void OnClose(int id, bool by_user); + void OnClick(int id); + void OnPermissionRequestComplete(int id); + void OnNavigate(); + + // A tracker object which manages the active notifications and the IDs + // that are used to refer to them over IPC. + ActiveNotificationTracker manager_; + + DISALLOW_COPY_AND_ASSIGN(NotificationProvider); +}; + +#endif // CONTENT_RENDERER_NOTIFICATION_PROVIDER_H_ diff --git a/content/renderer/speech_input_dispatcher.cc b/content/renderer/speech_input_dispatcher.cc new file mode 100644 index 0000000..8175e40 --- /dev/null +++ b/content/renderer/speech_input_dispatcher.cc @@ -0,0 +1,95 @@ +// Copyright (c) 2010 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/renderer/speech_input_dispatcher.h" + +#include "base/utf_string_conversions.h" +#include "chrome/renderer/render_view.h" +#include "content/common/speech_input_messages.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebSpeechInputListener.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" + +using WebKit::WebFrame; + +SpeechInputDispatcher::SpeechInputDispatcher( + RenderView* render_view, + WebKit::WebSpeechInputListener* listener) + : RenderViewObserver(render_view), + listener_(listener) { +} + +bool SpeechInputDispatcher::OnMessageReceived(const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(SpeechInputDispatcher, message) + IPC_MESSAGE_HANDLER(SpeechInputMsg_SetRecognitionResult, + OnSpeechRecognitionResult) + IPC_MESSAGE_HANDLER(SpeechInputMsg_RecordingComplete, + OnSpeechRecordingComplete) + IPC_MESSAGE_HANDLER(SpeechInputMsg_RecognitionComplete, + OnSpeechRecognitionComplete) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +bool SpeechInputDispatcher::startRecognition( + int request_id, + const WebKit::WebRect& element_rect, + const WebKit::WebString& language, + const WebKit::WebString& grammar, + const WebKit::WebSecurityOrigin& origin) { + VLOG(1) << "SpeechInputDispatcher::startRecognition enter"; + + SpeechInputHostMsg_StartRecognition_Params params; + params.grammar = UTF16ToUTF8(grammar); + params.language = UTF16ToUTF8(language); + params.origin_url = UTF16ToUTF8(origin.toString()); + params.render_view_id = routing_id(); + params.request_id = request_id; + gfx::Size scroll = render_view()->webview()->mainFrame()->scrollOffset(); + params.element_rect = element_rect; + params.element_rect.Offset(-scroll.width(), -scroll.height()); + + Send(new SpeechInputHostMsg_StartRecognition(params)); + VLOG(1) << "SpeechInputDispatcher::startRecognition exit"; + return true; +} + +void SpeechInputDispatcher::cancelRecognition(int request_id) { + VLOG(1) << "SpeechInputDispatcher::cancelRecognition enter"; + Send(new SpeechInputHostMsg_CancelRecognition(routing_id(), request_id)); + VLOG(1) << "SpeechInputDispatcher::cancelRecognition exit"; +} + +void SpeechInputDispatcher::stopRecording(int request_id) { + VLOG(1) << "SpeechInputDispatcher::stopRecording enter"; + Send(new SpeechInputHostMsg_StopRecording(routing_id(), request_id)); + VLOG(1) << "SpeechInputDispatcher::stopRecording exit"; +} + +void SpeechInputDispatcher::OnSpeechRecognitionResult( + int request_id, const speech_input::SpeechInputResultArray& result) { + VLOG(1) << "SpeechInputDispatcher::OnSpeechRecognitionResult enter"; + WebKit::WebSpeechInputResultArray webkit_result(result.size()); + for (size_t i = 0; i < result.size(); ++i) + webkit_result[i].set(result[i].utterance, result[i].confidence); + listener_->setRecognitionResult(request_id, webkit_result); + VLOG(1) << "SpeechInputDispatcher::OnSpeechRecognitionResult exit"; +} + +void SpeechInputDispatcher::OnSpeechRecordingComplete(int request_id) { + VLOG(1) << "SpeechInputDispatcher::OnSpeechRecordingComplete enter"; + listener_->didCompleteRecording(request_id); + VLOG(1) << "SpeechInputDispatcher::OnSpeechRecordingComplete exit"; +} + +void SpeechInputDispatcher::OnSpeechRecognitionComplete(int request_id) { + VLOG(1) << "SpeechInputDispatcher::OnSpeechRecognitionComplete enter"; + listener_->didCompleteRecognition(request_id); + VLOG(1) << "SpeechInputDispatcher::OnSpeechRecognitionComplete exit"; +} diff --git a/content/renderer/speech_input_dispatcher.h b/content/renderer/speech_input_dispatcher.h new file mode 100644 index 0000000..44513bb --- /dev/null +++ b/content/renderer/speech_input_dispatcher.h @@ -0,0 +1,51 @@ +// Copyright (c) 2010 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_RENDERER_SPEECH_INPUT_DISPATCHER_H_ +#define CONTENT_RENDERER_SPEECH_INPUT_DISPATCHER_H_ + +#include "base/basictypes.h" +#include "chrome/renderer/render_view_observer.h" +#include "content/common/speech_input_result.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebSpeechInputController.h" + +class GURL; + +namespace WebKit { +class WebSpeechInputListener; +} + +// SpeechInputDispatcher is a delegate for speech input messages used by WebKit. +// It's the complement of SpeechInputDispatcherHost (owned by RenderViewHost). +class SpeechInputDispatcher : public RenderViewObserver, + public WebKit::WebSpeechInputController { + public: + SpeechInputDispatcher(RenderView* render_view, + WebKit::WebSpeechInputListener* listener); + + private: + // RenderView::Observer implementation. + virtual bool OnMessageReceived(const IPC::Message& message); + + // WebKit::WebSpeechInputController. + virtual bool startRecognition(int request_id, + const WebKit::WebRect& element_rect, + const WebKit::WebString& language, + const WebKit::WebString& grammar, + const WebKit::WebSecurityOrigin& origin); + + virtual void cancelRecognition(int request_id); + virtual void stopRecording(int request_id); + + void OnSpeechRecognitionResult( + int request_id, const speech_input::SpeechInputResultArray& result); + void OnSpeechRecordingComplete(int request_id); + void OnSpeechRecognitionComplete(int request_id); + + WebKit::WebSpeechInputListener* listener_; + + DISALLOW_COPY_AND_ASSIGN(SpeechInputDispatcher); +}; + +#endif // CHROME_RENDERER_SPEECH_INPUT_DISPATCHER_H_ |