diff options
author | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-12-02 19:16:07 +0000 |
---|---|---|
committer | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-12-02 19:16:07 +0000 |
commit | 4b580bf3020b1e0eaf5b7efad50896b4c62474c5 (patch) | |
tree | 94f893bf3422dccda5e4bc05e4f8b8cca0d62638 /ipc/ipc_channel_proxy.cc | |
parent | e669998f4edaa156aafbe2fb93b3e3dae1ebd06c (diff) | |
download | chromium_src-4b580bf3020b1e0eaf5b7efad50896b4c62474c5.zip chromium_src-4b580bf3020b1e0eaf5b7efad50896b4c62474c5.tar.gz chromium_src-4b580bf3020b1e0eaf5b7efad50896b4c62474c5.tar.bz2 |
Add a base class for objects that want to filter messages on the IO thread. I'll switch the filters to it in future separate changes.
I've also taken out the special case for an initial filter from the IPC classes. The reason it existed was that there was a race condition of some messages not being filtered if a filter is added after construction but before launching the peer process. Taking it out allows us to add more than one filter and makes things a little cleaner.
Review URL: http://codereview.chromium.org/5513001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@68043 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ipc/ipc_channel_proxy.cc')
-rw-r--r-- | ipc/ipc_channel_proxy.cc | 61 |
1 files changed, 41 insertions, 20 deletions
diff --git a/ipc/ipc_channel_proxy.cc b/ipc/ipc_channel_proxy.cc index f05ae485..8450c28 100644 --- a/ipc/ipc_channel_proxy.cc +++ b/ipc/ipc_channel_proxy.cc @@ -61,7 +61,6 @@ void ChannelProxy::MessageFilter::OnDestruct() const { //------------------------------------------------------------------------------ ChannelProxy::Context::Context(Channel::Listener* listener, - MessageFilter* filter, MessageLoop* ipc_message_loop) : listener_message_loop_(MessageLoop::current()), listener_(listener), @@ -69,8 +68,6 @@ ChannelProxy::Context::Context(Channel::Listener* listener, channel_(NULL), peer_pid_(0), channel_connected_called_(false) { - if (filter) - filters_.push_back(make_scoped_refptr(filter)); } void ChannelProxy::Context::CreateChannel(const std::string& id, @@ -118,6 +115,12 @@ void ChannelProxy::Context::OnMessageReceivedNoFilter(const Message& message) { // Called on the IPC::Channel thread void ChannelProxy::Context::OnChannelConnected(int32 peer_pid) { + // Add any pending filters. This avoids a race condition where someone + // creates a ChannelProxy, calls AddFilter, and then right after starts the + // peer process. The IO thread could receive a message before the task to add + // the filter is run on the IO thread. + OnAddFilter(); + peer_pid_ = peer_pid; for (size_t i = 0; i < filters_.size(); ++i) filters_[i]->OnChannelConnected(peer_pid); @@ -189,13 +192,24 @@ void ChannelProxy::Context::OnSendMessage(Message* message) { } // Called on the IPC::Channel thread -void ChannelProxy::Context::OnAddFilter(MessageFilter* filter) { - filters_.push_back(make_scoped_refptr(filter)); +void ChannelProxy::Context::OnAddFilter() { + std::vector<scoped_refptr<MessageFilter> > filters; + { + AutoLock auto_lock(pending_filters_lock_); + filters.swap(pending_filters_); + } + + for (size_t i = 0; i < filters.size(); ++i) { + filters_.push_back(filters[i]); - // If the channel has already been created, then we need to send this message - // so that the filter gets access to the Channel. - if (channel_) - filter->OnFilterAdded(channel_); + // If the channel has already been created, then we need to send this + // message so that the filter gets access to the Channel. + if (channel_) + filters[i]->OnFilterAdded(channel_); + // Ditto for the peer process id. + if (peer_pid_) + filters[i]->OnChannelConnected(peer_pid_); + } } // Called on the IPC::Channel thread @@ -212,6 +226,15 @@ void ChannelProxy::Context::OnRemoveFilter(MessageFilter* filter) { } // Called on the listener's thread +void ChannelProxy::Context::AddFilter(MessageFilter* filter) { + AutoLock auto_lock(pending_filters_lock_); + pending_filters_.push_back(make_scoped_refptr(filter)); + ipc_message_loop_->PostTask( + FROM_HERE, + NewRunnableMethod(this, &Context::OnAddFilter)); +} + +// Called on the listener's thread void ChannelProxy::Context::OnDispatchMessage(const Message& message) { if (!listener_) return; @@ -255,15 +278,18 @@ void ChannelProxy::Context::OnDispatchError() { //----------------------------------------------------------------------------- -ChannelProxy::ChannelProxy(const std::string& channel_id, Channel::Mode mode, - Channel::Listener* listener, MessageFilter* filter, +ChannelProxy::ChannelProxy(const std::string& channel_id, + Channel::Mode mode, + Channel::Listener* listener, MessageLoop* ipc_thread) - : context_(new Context(listener, filter, ipc_thread)) { + : context_(new Context(listener, ipc_thread)) { Init(channel_id, mode, ipc_thread, true); } -ChannelProxy::ChannelProxy(const std::string& channel_id, Channel::Mode mode, - MessageLoop* ipc_thread, Context* context, +ChannelProxy::ChannelProxy(const std::string& channel_id, + Channel::Mode mode, + MessageLoop* ipc_thread, + Context* context, bool create_pipe_now) : context_(context) { Init(channel_id, mode, ipc_thread, create_pipe_now); @@ -314,12 +340,7 @@ bool ChannelProxy::Send(Message* message) { } void ChannelProxy::AddFilter(MessageFilter* filter) { - context_->ipc_message_loop()->PostTask( - FROM_HERE, - NewRunnableMethod( - context_.get(), - &Context::OnAddFilter, - make_scoped_refptr(filter))); + context_->AddFilter(filter); } void ChannelProxy::RemoveFilter(MessageFilter* filter) { |