1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "build/build_config.h"
7 #include "base/message_loop/message_loop.h"
8 #include "base/pickle.h"
9 #include "base/threading/thread.h"
10 #include "ipc/ipc_message.h"
11 #include "ipc/ipc_message_macros.h"
12 #include "ipc/ipc_test_base.h"
13 #include "ipc/message_filter.h"
17 #if defined(IPC_MESSAGE_START)
18 #undef IPC_MESSAGE_START
26 static void Send(IPC::Sender
* sender
,
29 const int IPC_MESSAGE_START
= message_class
;
30 IPC::Message
* message
= new IPC::Message(0,
32 IPC::Message::PRIORITY_NORMAL
);
33 message
->WriteInt(command
);
34 sender
->Send(message
);
37 class QuitListener
: public IPC::Listener
{
40 virtual ~QuitListener() {}
42 virtual bool OnMessageReceived(const IPC::Message
& message
) OVERRIDE
{
43 PickleIterator
iter(message
);
46 EXPECT_TRUE(iter
.ReadInt(&command
));
48 base::MessageLoop::current()->QuitWhenIdle();
54 class ChannelReflectorListener
: public IPC::Listener
{
56 ChannelReflectorListener() : channel_(NULL
) {}
57 virtual ~ChannelReflectorListener() {}
59 void Init(IPC::Channel
* channel
) {
64 virtual bool OnMessageReceived(const IPC::Message
& message
) OVERRIDE
{
67 PickleIterator
iter(message
);
70 EXPECT_TRUE(iter
.ReadInt(&command
));
71 if (command
== QUIT
) {
72 channel_
->Send(new IPC::Message(message
));
73 base::MessageLoop::current()->QuitWhenIdle();
77 channel_
->Send(new IPC::Message(message
));
82 IPC::Channel
* channel_
;
85 class MessageCountFilter
: public IPC::MessageFilter
{
96 : messages_received_(0),
97 supported_message_class_(0),
98 is_global_filter_(true),
99 last_filter_event_(NONE
),
100 message_filtering_enabled_(false) {}
102 MessageCountFilter(uint32 supported_message_class
)
103 : messages_received_(0),
104 supported_message_class_(supported_message_class
),
105 is_global_filter_(false),
106 last_filter_event_(NONE
),
107 message_filtering_enabled_(false) {}
109 virtual void OnFilterAdded(IPC::Channel
* channel
) OVERRIDE
{
110 EXPECT_TRUE(channel
);
111 EXPECT_EQ(NONE
, last_filter_event_
);
112 last_filter_event_
= FILTER_ADDED
;
115 virtual void OnChannelConnected(int32_t peer_pid
) OVERRIDE
{
116 EXPECT_EQ(FILTER_ADDED
, last_filter_event_
);
117 EXPECT_NE(static_cast<int32_t>(base::kNullProcessId
), peer_pid
);
118 last_filter_event_
= CHANNEL_CONNECTED
;
121 virtual void OnChannelError() OVERRIDE
{
122 EXPECT_EQ(CHANNEL_CONNECTED
, last_filter_event_
);
123 last_filter_event_
= CHANNEL_ERROR
;
126 virtual void OnChannelClosing() OVERRIDE
{
127 // We may or may not have gotten OnChannelError; if not, the last event has
128 // to be OnChannelConnected.
129 if (last_filter_event_
!= CHANNEL_ERROR
)
130 EXPECT_EQ(CHANNEL_CONNECTED
, last_filter_event_
);
131 last_filter_event_
= CHANNEL_CLOSING
;
134 virtual void OnFilterRemoved() OVERRIDE
{
135 // If the channel didn't get a chance to connect, we might see the
136 // OnFilterRemoved event with no other events preceding it. We still want
137 // OnFilterRemoved to be called to allow for deleting the Filter.
138 if (last_filter_event_
!= NONE
)
139 EXPECT_EQ(CHANNEL_CLOSING
, last_filter_event_
);
140 last_filter_event_
= FILTER_REMOVED
;
143 virtual bool OnMessageReceived(const IPC::Message
& message
) OVERRIDE
{
144 // We should always get the OnFilterAdded and OnChannelConnected events
145 // prior to any messages.
146 EXPECT_EQ(CHANNEL_CONNECTED
, last_filter_event_
);
148 if (!is_global_filter_
) {
149 EXPECT_EQ(supported_message_class_
, IPC_MESSAGE_CLASS(message
));
151 ++messages_received_
;
152 return message_filtering_enabled_
;
155 virtual bool GetSupportedMessageClasses(
156 std::vector
<uint32
>* supported_message_classes
) const OVERRIDE
{
157 if (is_global_filter_
)
159 supported_message_classes
->push_back(supported_message_class_
);
163 void set_message_filtering_enabled(bool enabled
) {
164 message_filtering_enabled_
= enabled
;
167 size_t messages_received() const { return messages_received_
; }
168 FilterEvent
last_filter_event() const { return last_filter_event_
; }
171 virtual ~MessageCountFilter() {}
173 size_t messages_received_
;
174 uint32 supported_message_class_
;
175 bool is_global_filter_
;
177 FilterEvent last_filter_event_
;
178 bool message_filtering_enabled_
;
181 class IPCChannelProxyTest
: public IPCTestBase
{
183 IPCChannelProxyTest() {}
184 virtual ~IPCChannelProxyTest() {}
186 virtual void SetUp() OVERRIDE
{
187 IPCTestBase::SetUp();
189 Init("ChannelProxyClient");
191 thread_
.reset(new base::Thread("ChannelProxyTestServerThread"));
192 base::Thread::Options options
;
193 options
.message_loop_type
= base::MessageLoop::TYPE_IO
;
194 thread_
->StartWithOptions(options
);
196 listener_
.reset(new QuitListener());
197 CreateChannelProxy(listener_
.get(), thread_
->message_loop_proxy().get());
199 ASSERT_TRUE(StartClient());
202 virtual void TearDown() {
203 DestroyChannelProxy();
206 IPCTestBase::TearDown();
209 void SendQuitMessageAndWaitForIdle() {
210 Send(sender(), -1, QUIT
);
211 base::MessageLoop::current()->Run();
212 EXPECT_TRUE(WaitForClientShutdown());
216 scoped_ptr
<base::Thread
> thread_
;
217 scoped_ptr
<QuitListener
> listener_
;
220 TEST_F(IPCChannelProxyTest
, MessageClassFilters
) {
221 // Construct a filter per message class.
222 std::vector
<scoped_refptr
<MessageCountFilter
> > class_filters
;
223 for (uint32 i
= 0; i
< LastIPCMsgStart
; ++i
) {
224 class_filters
.push_back(make_scoped_refptr(
225 new MessageCountFilter(i
)));
226 channel_proxy()->AddFilter(class_filters
.back().get());
229 // Send a message for each class; each filter should receive just one message.
230 for (uint32 i
= 0; i
< LastIPCMsgStart
; ++i
)
231 Send(sender(), i
, SEND
);
233 // Send some messages not assigned to a specific or valid message class.
234 Send(sender(), -1, SEND
);
235 Send(sender(), LastIPCMsgStart
, SEND
);
236 Send(sender(), LastIPCMsgStart
+ 1, SEND
);
238 // Each filter should have received just the one sent message of the
239 // corresponding class.
240 SendQuitMessageAndWaitForIdle();
241 for (size_t i
= 0; i
< class_filters
.size(); ++i
)
242 EXPECT_EQ(1U, class_filters
[i
]->messages_received());
245 TEST_F(IPCChannelProxyTest
, GlobalAndMessageClassFilters
) {
246 // Add a class and global filter.
247 const int kMessageClass
= 7;
248 scoped_refptr
<MessageCountFilter
> class_filter(
249 new MessageCountFilter(kMessageClass
));
250 class_filter
->set_message_filtering_enabled(false);
251 channel_proxy()->AddFilter(class_filter
.get());
253 scoped_refptr
<MessageCountFilter
> global_filter(new MessageCountFilter());
254 global_filter
->set_message_filtering_enabled(false);
255 channel_proxy()->AddFilter(global_filter
.get());
257 // A message of class |kMessageClass| should be seen by both the global
258 // filter and |kMessageClass|-specific filter.
259 Send(sender(), kMessageClass
, SEND
);
261 // A message of a different class should be seen only by the global filter.
262 Send(sender(), kMessageClass
+ 1, SEND
);
264 // Flush all messages.
265 SendQuitMessageAndWaitForIdle();
267 // The class filter should have received only the class-specific message.
268 EXPECT_EQ(1U, class_filter
->messages_received());
270 // The global filter should have received both SEND messages, as well as the
271 // final QUIT message.
272 EXPECT_EQ(3U, global_filter
->messages_received());
275 TEST_F(IPCChannelProxyTest
, FilterRemoval
) {
276 // Add a class and global filter.
277 const int kMessageClass
= 7;
278 scoped_refptr
<MessageCountFilter
> class_filter(
279 new MessageCountFilter(kMessageClass
));
280 scoped_refptr
<MessageCountFilter
> global_filter(new MessageCountFilter());
282 // Add and remove both types of filters.
283 channel_proxy()->AddFilter(class_filter
.get());
284 channel_proxy()->AddFilter(global_filter
.get());
285 channel_proxy()->RemoveFilter(global_filter
.get());
286 channel_proxy()->RemoveFilter(class_filter
.get());
288 // Send some messages; they should not be seen by either filter.
289 Send(sender(), 0, SEND
);
290 Send(sender(), kMessageClass
, SEND
);
292 // Ensure that the filters were removed and did not receive any messages.
293 SendQuitMessageAndWaitForIdle();
294 EXPECT_EQ(MessageCountFilter::FILTER_REMOVED
,
295 global_filter
->last_filter_event());
296 EXPECT_EQ(MessageCountFilter::FILTER_REMOVED
,
297 class_filter
->last_filter_event());
298 EXPECT_EQ(0U, class_filter
->messages_received());
299 EXPECT_EQ(0U, global_filter
->messages_received());
302 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(ChannelProxyClient
) {
303 base::MessageLoopForIO main_message_loop
;
304 ChannelReflectorListener listener
;
305 IPC::Channel
channel(IPCTestBase::GetChannelName("ChannelProxyClient"),
306 IPC::Channel::MODE_CLIENT
,
308 CHECK(channel
.Connect());
309 listener
.Init(&channel
);
311 base::MessageLoop::current()->Run();