| Index: ipc/ipc_channel_proxy.cc
|
| ===================================================================
|
| --- ipc/ipc_channel_proxy.cc (revision 67520)
|
| +++ ipc/ipc_channel_proxy.cc (working copy)
|
| @@ -61,7 +61,6 @@
|
| //------------------------------------------------------------------------------
|
|
|
| ChannelProxy::Context::Context(Channel::Listener* listener,
|
| - MessageFilter* filter,
|
| MessageLoop* ipc_message_loop)
|
| : listener_message_loop_(MessageLoop::current()),
|
| listener_(listener),
|
| @@ -69,8 +68,6 @@
|
| 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 @@
|
|
|
| // 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 @@
|
| }
|
|
|
| // 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_);
|
| + }
|
|
|
| - // 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_);
|
| + 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_)
|
| + 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 @@
|
| }
|
|
|
| // 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 @@
|
|
|
| //-----------------------------------------------------------------------------
|
|
|
| -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 @@
|
| }
|
|
|
| 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) {
|
|
|