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/pickle.h"
8 #include "base/threading/thread.h"
9 #include "ipc/ipc_message.h"
10 #include "ipc/ipc_test_base.h"
11 #include "ipc/message_filter.h"
13 // Get basic type definitions.
14 #define IPC_MESSAGE_IMPL
15 #include "ipc/ipc_channel_proxy_unittest_messages.h"
17 // Generate constructors.
18 #include "ipc/struct_constructor_macros.h"
19 #include "ipc/ipc_channel_proxy_unittest_messages.h"
21 // Generate destructors.
22 #include "ipc/struct_destructor_macros.h"
23 #include "ipc/ipc_channel_proxy_unittest_messages.h"
25 // Generate param traits write methods.
26 #include "ipc/param_traits_write_macros.h"
28 #include "ipc/ipc_channel_proxy_unittest_messages.h"
31 // Generate param traits read methods.
32 #include "ipc/param_traits_read_macros.h"
34 #include "ipc/ipc_channel_proxy_unittest_messages.h"
37 // Generate param traits log methods.
38 #include "ipc/param_traits_log_macros.h"
40 #include "ipc/ipc_channel_proxy_unittest_messages.h"
46 class QuitListener
: public IPC::Listener
{
48 QuitListener() : bad_message_received_(false) {}
50 bool OnMessageReceived(const IPC::Message
& message
) override
{
51 IPC_BEGIN_MESSAGE_MAP(QuitListener
, message
)
52 IPC_MESSAGE_HANDLER(WorkerMsg_Quit
, OnQuit
)
53 IPC_MESSAGE_HANDLER(TestMsg_BadMessage
, OnBadMessage
)
58 void OnBadMessageReceived(const IPC::Message
& message
) override
{
59 bad_message_received_
= true;
63 base::MessageLoop::current()->QuitWhenIdle();
66 void OnBadMessage(const BadType
& bad_type
) {
67 // Should never be called since IPC wouldn't be deserialized correctly.
71 bool bad_message_received_
;
74 class ChannelReflectorListener
: public IPC::Listener
{
76 ChannelReflectorListener() : channel_(NULL
) {}
78 void Init(IPC::Channel
* channel
) {
83 bool OnMessageReceived(const IPC::Message
& message
) override
{
84 IPC_BEGIN_MESSAGE_MAP(ChannelReflectorListener
, message
)
85 IPC_MESSAGE_HANDLER(TestMsg_Bounce
, OnTestBounce
)
86 IPC_MESSAGE_HANDLER(TestMsg_SendBadMessage
, OnSendBadMessage
)
87 IPC_MESSAGE_HANDLER(UtilityMsg_Bounce
, OnUtilityBounce
)
88 IPC_MESSAGE_HANDLER(WorkerMsg_Bounce
, OnBounce
)
89 IPC_MESSAGE_HANDLER(WorkerMsg_Quit
, OnQuit
)
95 channel_
->Send(new TestMsg_Bounce());
98 void OnSendBadMessage() {
99 channel_
->Send(new TestMsg_BadMessage(BadType()));
102 void OnUtilityBounce() {
103 channel_
->Send(new UtilityMsg_Bounce());
107 channel_
->Send(new WorkerMsg_Bounce());
111 channel_
->Send(new WorkerMsg_Quit());
112 base::MessageLoop::current()->QuitWhenIdle();
116 IPC::Channel
* channel_
;
119 class MessageCountFilter
: public IPC::MessageFilter
{
130 : messages_received_(0),
131 supported_message_class_(0),
132 is_global_filter_(true),
133 last_filter_event_(NONE
),
134 message_filtering_enabled_(false) {}
136 MessageCountFilter(uint32 supported_message_class
)
137 : messages_received_(0),
138 supported_message_class_(supported_message_class
),
139 is_global_filter_(false),
140 last_filter_event_(NONE
),
141 message_filtering_enabled_(false) {}
143 void OnFilterAdded(IPC::Sender
* sender
) override
{
145 EXPECT_EQ(NONE
, last_filter_event_
);
146 last_filter_event_
= FILTER_ADDED
;
149 void OnChannelConnected(int32_t peer_pid
) override
{
150 EXPECT_EQ(FILTER_ADDED
, last_filter_event_
);
151 EXPECT_NE(static_cast<int32_t>(base::kNullProcessId
), peer_pid
);
152 last_filter_event_
= CHANNEL_CONNECTED
;
155 void OnChannelError() override
{
156 EXPECT_EQ(CHANNEL_CONNECTED
, last_filter_event_
);
157 last_filter_event_
= CHANNEL_ERROR
;
160 void OnChannelClosing() override
{
161 // We may or may not have gotten OnChannelError; if not, the last event has
162 // to be OnChannelConnected.
163 if (last_filter_event_
!= CHANNEL_ERROR
)
164 EXPECT_EQ(CHANNEL_CONNECTED
, last_filter_event_
);
165 last_filter_event_
= CHANNEL_CLOSING
;
168 void OnFilterRemoved() override
{
169 // If the channel didn't get a chance to connect, we might see the
170 // OnFilterRemoved event with no other events preceding it. We still want
171 // OnFilterRemoved to be called to allow for deleting the Filter.
172 if (last_filter_event_
!= NONE
)
173 EXPECT_EQ(CHANNEL_CLOSING
, last_filter_event_
);
174 last_filter_event_
= FILTER_REMOVED
;
177 bool OnMessageReceived(const IPC::Message
& message
) override
{
178 // We should always get the OnFilterAdded and OnChannelConnected events
179 // prior to any messages.
180 EXPECT_EQ(CHANNEL_CONNECTED
, last_filter_event_
);
182 if (!is_global_filter_
) {
183 EXPECT_EQ(supported_message_class_
, IPC_MESSAGE_CLASS(message
));
185 ++messages_received_
;
187 if (!message_filtering_enabled_
)
191 IPC_BEGIN_MESSAGE_MAP(MessageCountFilter
, message
)
192 IPC_MESSAGE_HANDLER(TestMsg_BadMessage
, OnBadMessage
)
193 IPC_MESSAGE_UNHANDLED(handled
= false)
194 IPC_END_MESSAGE_MAP()
198 void OnBadMessage(const BadType
& bad_type
) {
199 // Should never be called since IPC wouldn't be deserialized correctly.
203 bool GetSupportedMessageClasses(
204 std::vector
<uint32
>* supported_message_classes
) const override
{
205 if (is_global_filter_
)
207 supported_message_classes
->push_back(supported_message_class_
);
211 void set_message_filtering_enabled(bool enabled
) {
212 message_filtering_enabled_
= enabled
;
215 size_t messages_received() const { return messages_received_
; }
216 FilterEvent
last_filter_event() const { return last_filter_event_
; }
219 ~MessageCountFilter() override
{}
221 size_t messages_received_
;
222 uint32 supported_message_class_
;
223 bool is_global_filter_
;
225 FilterEvent last_filter_event_
;
226 bool message_filtering_enabled_
;
229 class IPCChannelProxyTest
: public IPCTestBase
{
231 IPCChannelProxyTest() {}
232 ~IPCChannelProxyTest() override
{}
234 void SetUp() override
{
235 IPCTestBase::SetUp();
237 Init("ChannelProxyClient");
239 thread_
.reset(new base::Thread("ChannelProxyTestServerThread"));
240 base::Thread::Options options
;
241 options
.message_loop_type
= base::MessageLoop::TYPE_IO
;
242 thread_
->StartWithOptions(options
);
244 listener_
.reset(new QuitListener());
245 CreateChannelProxy(listener_
.get(), thread_
->task_runner().get());
247 ASSERT_TRUE(StartClient());
250 void TearDown() override
{
251 DestroyChannelProxy();
254 IPCTestBase::TearDown();
257 void SendQuitMessageAndWaitForIdle() {
258 sender()->Send(new WorkerMsg_Quit
);
259 base::MessageLoop::current()->Run();
260 EXPECT_TRUE(WaitForClientShutdown());
263 bool DidListenerGetBadMessage() {
264 return listener_
->bad_message_received_
;
268 scoped_ptr
<base::Thread
> thread_
;
269 scoped_ptr
<QuitListener
> listener_
;
272 TEST_F(IPCChannelProxyTest
, MessageClassFilters
) {
273 // Construct a filter per message class.
274 std::vector
<scoped_refptr
<MessageCountFilter
> > class_filters
;
275 class_filters
.push_back(make_scoped_refptr(
276 new MessageCountFilter(TestMsgStart
)));
277 class_filters
.push_back(make_scoped_refptr(
278 new MessageCountFilter(UtilityMsgStart
)));
279 for (size_t i
= 0; i
< class_filters
.size(); ++i
)
280 channel_proxy()->AddFilter(class_filters
[i
].get());
282 // Send a message for each class; each filter should receive just one message.
283 sender()->Send(new TestMsg_Bounce());
284 sender()->Send(new UtilityMsg_Bounce());
286 // Send some messages not assigned to a specific or valid message class.
287 sender()->Send(new WorkerMsg_Bounce
);
289 // Each filter should have received just the one sent message of the
290 // corresponding class.
291 SendQuitMessageAndWaitForIdle();
292 for (size_t i
= 0; i
< class_filters
.size(); ++i
)
293 EXPECT_EQ(1U, class_filters
[i
]->messages_received());
296 TEST_F(IPCChannelProxyTest
, GlobalAndMessageClassFilters
) {
297 // Add a class and global filter.
298 scoped_refptr
<MessageCountFilter
> class_filter(
299 new MessageCountFilter(TestMsgStart
));
300 class_filter
->set_message_filtering_enabled(false);
301 channel_proxy()->AddFilter(class_filter
.get());
303 scoped_refptr
<MessageCountFilter
> global_filter(new MessageCountFilter());
304 global_filter
->set_message_filtering_enabled(false);
305 channel_proxy()->AddFilter(global_filter
.get());
307 // A message of class Test should be seen by both the global filter and
308 // Test-specific filter.
309 sender()->Send(new TestMsg_Bounce
);
311 // A message of a different class should be seen only by the global filter.
312 sender()->Send(new UtilityMsg_Bounce
);
314 // Flush all messages.
315 SendQuitMessageAndWaitForIdle();
317 // The class filter should have received only the class-specific message.
318 EXPECT_EQ(1U, class_filter
->messages_received());
320 // The global filter should have received both messages, as well as the final
322 EXPECT_EQ(3U, global_filter
->messages_received());
325 TEST_F(IPCChannelProxyTest
, FilterRemoval
) {
326 // Add a class and global filter.
327 scoped_refptr
<MessageCountFilter
> class_filter(
328 new MessageCountFilter(TestMsgStart
));
329 scoped_refptr
<MessageCountFilter
> global_filter(new MessageCountFilter());
331 // Add and remove both types of filters.
332 channel_proxy()->AddFilter(class_filter
.get());
333 channel_proxy()->AddFilter(global_filter
.get());
334 channel_proxy()->RemoveFilter(global_filter
.get());
335 channel_proxy()->RemoveFilter(class_filter
.get());
337 // Send some messages; they should not be seen by either filter.
338 sender()->Send(new TestMsg_Bounce
);
339 sender()->Send(new UtilityMsg_Bounce
);
341 // Ensure that the filters were removed and did not receive any messages.
342 SendQuitMessageAndWaitForIdle();
343 EXPECT_EQ(MessageCountFilter::FILTER_REMOVED
,
344 global_filter
->last_filter_event());
345 EXPECT_EQ(MessageCountFilter::FILTER_REMOVED
,
346 class_filter
->last_filter_event());
347 EXPECT_EQ(0U, class_filter
->messages_received());
348 EXPECT_EQ(0U, global_filter
->messages_received());
351 // The test that follow trigger DCHECKS in debug build.
352 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
354 TEST_F(IPCChannelProxyTest
, BadMessageOnListenerThread
) {
355 scoped_refptr
<MessageCountFilter
> class_filter(
356 new MessageCountFilter(TestMsgStart
));
357 class_filter
->set_message_filtering_enabled(false);
358 channel_proxy()->AddFilter(class_filter
.get());
360 sender()->Send(new TestMsg_SendBadMessage());
362 SendQuitMessageAndWaitForIdle();
363 EXPECT_TRUE(DidListenerGetBadMessage());
366 TEST_F(IPCChannelProxyTest
, BadMessageOnIPCThread
) {
367 scoped_refptr
<MessageCountFilter
> class_filter(
368 new MessageCountFilter(TestMsgStart
));
369 class_filter
->set_message_filtering_enabled(true);
370 channel_proxy()->AddFilter(class_filter
.get());
372 sender()->Send(new TestMsg_SendBadMessage());
374 SendQuitMessageAndWaitForIdle();
375 EXPECT_TRUE(DidListenerGetBadMessage());
378 class IPCChannelBadMessageTest
: public IPCTestBase
{
380 void SetUp() override
{
381 IPCTestBase::SetUp();
383 Init("ChannelProxyClient");
385 listener_
.reset(new QuitListener());
386 CreateChannel(listener_
.get());
387 ASSERT_TRUE(ConnectChannel());
389 ASSERT_TRUE(StartClient());
392 void TearDown() override
{
394 IPCTestBase::TearDown();
397 void SendQuitMessageAndWaitForIdle() {
398 sender()->Send(new WorkerMsg_Quit
);
399 base::MessageLoop::current()->Run();
400 EXPECT_TRUE(WaitForClientShutdown());
403 bool DidListenerGetBadMessage() {
404 return listener_
->bad_message_received_
;
408 scoped_ptr
<QuitListener
> listener_
;
412 // TODO(jam): for some reason this is flaky on win buildbots.
413 TEST_F(IPCChannelBadMessageTest
, BadMessage
) {
414 sender()->Send(new TestMsg_SendBadMessage());
415 SendQuitMessageAndWaitForIdle();
416 EXPECT_TRUE(DidListenerGetBadMessage());
422 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(ChannelProxyClient
) {
423 base::MessageLoopForIO main_message_loop
;
424 ChannelReflectorListener listener
;
425 scoped_ptr
<IPC::Channel
> channel(IPC::Channel::CreateClient(
426 IPCTestBase::GetChannelName("ChannelProxyClient"),
428 CHECK(channel
->Connect());
429 listener
.Init(channel
.get());
431 base::MessageLoop::current()->Run();