1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/chromium/src/chrome/common/ipc_channel_proxy.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,209 @@ 1.4 +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1.5 +// Use of this source code is governed by a BSD-style license that can be 1.6 +// found in the LICENSE file. 1.7 + 1.8 +#ifndef CHROME_COMMON_IPC_CHANNEL_PROXY_H__ 1.9 +#define CHROME_COMMON_IPC_CHANNEL_PROXY_H__ 1.10 + 1.11 +#include <vector> 1.12 +#include "base/lock.h" 1.13 +#include "base/ref_counted.h" 1.14 +#include "chrome/common/ipc_channel.h" 1.15 + 1.16 +class MessageLoop; 1.17 + 1.18 +namespace IPC { 1.19 + 1.20 +//----------------------------------------------------------------------------- 1.21 +// IPC::ChannelProxy 1.22 +// 1.23 +// This class is a helper class that is useful when you wish to run an IPC 1.24 +// channel on a background thread. It provides you with the option of either 1.25 +// handling IPC messages on that background thread or having them dispatched to 1.26 +// your main thread (the thread on which the IPC::ChannelProxy is created). 1.27 +// 1.28 +// The API for an IPC::ChannelProxy is very similar to that of an IPC::Channel. 1.29 +// When you send a message to an IPC::ChannelProxy, the message is routed to 1.30 +// the background thread, where it is then passed to the IPC::Channel's Send 1.31 +// method. This means that you can send a message from your thread and your 1.32 +// message will be sent over the IPC channel when possible instead of being 1.33 +// delayed until your thread returns to its message loop. (Often IPC messages 1.34 +// will queue up on the IPC::Channel when there is a lot of traffic, and the 1.35 +// channel will not get cycles to flush its message queue until the thread, on 1.36 +// which it is running, returns to its message loop.) 1.37 +// 1.38 +// An IPC::ChannelProxy can have a MessageFilter associated with it, which will 1.39 +// be notified of incoming messages on the IPC::Channel's thread. This gives 1.40 +// the consumer of IPC::ChannelProxy the ability to respond to incoming 1.41 +// messages on this background thread instead of on their own thread, which may 1.42 +// be bogged down with other processing. The result can be greatly improved 1.43 +// latency for messages that can be handled on a background thread. 1.44 +// 1.45 +// The consumer of IPC::ChannelProxy is responsible for allocating the Thread 1.46 +// instance where the IPC::Channel will be created and operated. 1.47 +// 1.48 +class ChannelProxy : public Message::Sender { 1.49 + public: 1.50 + // A class that receives messages on the thread where the IPC channel is 1.51 + // running. It can choose to prevent the default action for an IPC message. 1.52 + class MessageFilter : public base::RefCountedThreadSafe<MessageFilter> { 1.53 + public: 1.54 + virtual ~MessageFilter() {} 1.55 + 1.56 + // Called on the background thread to provide the filter with access to the 1.57 + // channel. Called when the IPC channel is initialized or when AddFilter 1.58 + // is called if the channel is already initialized. 1.59 + virtual void OnFilterAdded(Channel* channel) {} 1.60 + 1.61 + // Called on the background thread when the filter has been removed from 1.62 + // the ChannelProxy and when the Channel is closing. After a filter is 1.63 + // removed, it will not be called again. 1.64 + virtual void OnFilterRemoved() {} 1.65 + 1.66 + // Called to inform the filter that the IPC channel is connected and we 1.67 + // have received the internal Hello message from the peer. 1.68 + virtual void OnChannelConnected(int32_t peer_pid) {} 1.69 + 1.70 + // Called when there is an error on the channel, typically that the channel 1.71 + // has been closed. 1.72 + virtual void OnChannelError() {} 1.73 + 1.74 + // Called to inform the filter that the IPC channel will be destroyed. 1.75 + // OnFilterRemoved is called immediately after this. 1.76 + virtual void OnChannelClosing() {} 1.77 + 1.78 + // Return true to indicate that the message was handled, or false to let 1.79 + // the message be handled in the default way. 1.80 + virtual bool OnMessageReceived(const Message& message) { 1.81 + return false; 1.82 + } 1.83 + }; 1.84 + 1.85 + // Initializes a channel proxy. The channel_id and mode parameters are 1.86 + // passed directly to the underlying IPC::Channel. The listener is called on 1.87 + // the thread that creates the ChannelProxy. The filter's OnMessageReceived 1.88 + // method is called on the thread where the IPC::Channel is running. The 1.89 + // filter may be null if the consumer is not interested in handling messages 1.90 + // on the background thread. Any message not handled by the filter will be 1.91 + // dispatched to the listener. The given message loop indicates where the 1.92 + // IPC::Channel should be created. 1.93 + ChannelProxy(const std::wstring& channel_id, Channel::Mode mode, 1.94 + Channel::Listener* listener, MessageFilter* filter, 1.95 + MessageLoop* ipc_thread_loop); 1.96 + 1.97 + ~ChannelProxy() { 1.98 + Close(); 1.99 + } 1.100 + 1.101 + // Close the IPC::Channel. This operation completes asynchronously, once the 1.102 + // background thread processes the command to close the channel. It is ok to 1.103 + // call this method multiple times. Redundant calls are ignored. 1.104 + // 1.105 + // WARNING: The MessageFilter object held by the ChannelProxy is also 1.106 + // released asynchronously, and it may in fact have its final reference 1.107 + // released on the background thread. The caller should be careful to deal 1.108 + // with / allow for this possibility. 1.109 + void Close(); 1.110 + 1.111 + // Send a message asynchronously. The message is routed to the background 1.112 + // thread where it is passed to the IPC::Channel's Send method. 1.113 + virtual bool Send(Message* message); 1.114 + 1.115 + // Used to intercept messages as they are received on the background thread. 1.116 + // 1.117 + // Ordinarily, messages sent to the ChannelProxy are routed to the matching 1.118 + // listener on the worker thread. This API allows code to intercept messages 1.119 + // before they are sent to the worker thread. 1.120 + void AddFilter(MessageFilter* filter); 1.121 + void RemoveFilter(MessageFilter* filter); 1.122 + 1.123 +#if defined(OS_POSIX) 1.124 + // Calls through to the underlying channel's methods. 1.125 + // TODO(playmobil): For now this is only implemented in the case of 1.126 + // create_pipe_now = true, we need to figure this out for the latter case. 1.127 + void GetClientFileDescriptorMapping(int *src_fd, int *dest_fd) const; 1.128 +#endif // defined(OS_POSIX) 1.129 + 1.130 + protected: 1.131 + class Context; 1.132 + // A subclass uses this constructor if it needs to add more information 1.133 + // to the internal state. If create_pipe_now is true, the pipe is created 1.134 + // immediately. Otherwise it's created on the IO thread. 1.135 + ChannelProxy(const std::wstring& channel_id, Channel::Mode mode, 1.136 + MessageLoop* ipc_thread_loop, Context* context, 1.137 + bool create_pipe_now); 1.138 + 1.139 + // Used internally to hold state that is referenced on the IPC thread. 1.140 + class Context : public base::RefCountedThreadSafe<Context>, 1.141 + public Channel::Listener { 1.142 + public: 1.143 + Context(Channel::Listener* listener, MessageFilter* filter, 1.144 + MessageLoop* ipc_thread); 1.145 + virtual ~Context() { } 1.146 + MessageLoop* ipc_message_loop() const { return ipc_message_loop_; } 1.147 + const std::wstring& channel_id() const { return channel_id_; } 1.148 + 1.149 + // Dispatches a message on the listener thread. 1.150 + void OnDispatchMessage(const Message& message); 1.151 + 1.152 + protected: 1.153 + // IPC::Channel::Listener methods: 1.154 + virtual void OnMessageReceived(const Message& message); 1.155 + virtual void OnChannelConnected(int32_t peer_pid); 1.156 + virtual void OnChannelError(); 1.157 + 1.158 + // Like OnMessageReceived but doesn't try the filters. 1.159 + void OnMessageReceivedNoFilter(const Message& message); 1.160 + 1.161 + // Gives the filters a chance at processing |message|. 1.162 + // Returns true if the message was processed, false otherwise. 1.163 + bool TryFilters(const Message& message); 1.164 + 1.165 + // Like Open and Close, but called on the IPC thread. 1.166 + virtual void OnChannelOpened(); 1.167 + virtual void OnChannelClosed(); 1.168 + 1.169 + // Called on the consumers thread when the ChannelProxy is closed. At that 1.170 + // point the consumer is telling us that they don't want to receive any 1.171 + // more messages, so we honor that wish by forgetting them! 1.172 + virtual void Clear() { listener_ = NULL; } 1.173 + 1.174 + private: 1.175 + friend class ChannelProxy; 1.176 + // Create the Channel 1.177 + void CreateChannel(const std::wstring& id, const Channel::Mode& mode); 1.178 + 1.179 + // Methods called via InvokeLater: 1.180 + void OnSendMessage(Message* message_ptr); 1.181 + void OnAddFilter(MessageFilter* filter); 1.182 + void OnRemoveFilter(MessageFilter* filter); 1.183 + void OnDispatchConnected(); 1.184 + void OnDispatchError(); 1.185 + 1.186 + MessageLoop* listener_message_loop_; 1.187 + Channel::Listener* listener_; 1.188 + 1.189 + // List of filters. This is only accessed on the IPC thread. 1.190 + std::vector<scoped_refptr<MessageFilter> > filters_; 1.191 + MessageLoop* ipc_message_loop_; 1.192 + Channel* channel_; 1.193 + std::wstring channel_id_; 1.194 + int peer_pid_; 1.195 + bool channel_connected_called_; 1.196 + }; 1.197 + 1.198 + Context* context() { return context_; } 1.199 + 1.200 + private: 1.201 + void Init(const std::wstring& channel_id, Channel::Mode mode, 1.202 + MessageLoop* ipc_thread_loop, bool create_pipe_now); 1.203 + 1.204 + // By maintaining this indirection (ref-counted) to our internal state, we 1.205 + // can safely be destroyed while the background thread continues to do stuff 1.206 + // that involves this data. 1.207 + scoped_refptr<Context> context_; 1.208 +}; 1.209 + 1.210 +} // namespace IPC 1.211 + 1.212 +#endif // CHROME_COMMON_IPC_CHANNEL_PROXY_H__